<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7718565330748264667</id><updated>2011-08-20T09:05:03.886-07:00</updated><category term='politics labour education'/><category term='technology'/><category term='h264'/><category term='emacs'/><category term='ps3'/><category term='wireless'/><category term='catholicism'/><category term='mormons religion gay rights'/><category term='ipod'/><category term='web'/><category term='DG834G'/><category term='apple'/><category term='family'/><category term='perl'/><category term='sony'/><category term='religion'/><category term='video'/><category term='firmware'/><category term='mencoder'/><category term='1.03.22'/><category term='books ebooks sony amazon drm'/><category term='netgear'/><title type='text'>Dynamic Thinking</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>52</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-5979931792019522568</id><published>2011-06-29T13:28:00.000-07:00</published><updated>2011-06-30T01:40:01.564-07:00</updated><title type='text'>Gran Turismo 5 (eventually, I'm assuming)</title><content type='html'>I'm occasionally a bit behind the curve when it comes to gaming.  Given the appalling state of some titles on release day, I've found that it's quite often sensible to wait a while until the first few patches have come out to address the glaring problems that the initial 'gold' build shipped with regardless.&lt;br /&gt;&lt;br /&gt;So it's not until today that I got a copy of Gran Turismo 5 for the PS3 (pre-owned).  I shove the disk in, and immediately have to download the better part of three quarters of a gigabyte of patches.  As soon as this non-backgroundable download starts, I fire up the PS2, switch to component input, restore a save of Shadow of the Colossus, and then spend the next half hour beating the 9th colossus.  I save that game, and switch back to the PS3 on HDMI in.  The patches still haven't finished downloading, so I switch to DVI in and boot the Linux box, do some simple updates and routine administration, then check in on the PS3 again.  Hey, all the patches are down!  Maybe I'll get the play the game.&lt;br /&gt;&lt;br /&gt;Or maybe not: right at the start, the game carries the advice that installing 8GB to hard disk can speed up loading times.  Now, if the game developers &lt;em&gt;felt the need to admit that&lt;/em&gt;, you know that there are going to be problems, so I click 'yes', and see an estimated time of a paltry 14 seconds.  Good!  Oh, wait: that's the &lt;em&gt;preparation&lt;/em&gt; time before it can &lt;em&gt;start&lt;/em&gt; installing: the actual estimate is more like 30 minutes.&lt;br /&gt;&lt;br /&gt;So, I take the time to write this blog post, and it's still installing.&lt;br /&gt;&lt;br /&gt;What the hell happened to console gaming?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-5979931792019522568?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/5979931792019522568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2011/06/gran-turismo-5-eventually-im-assuming.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5979931792019522568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5979931792019522568'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2011/06/gran-turismo-5-eventually-im-assuming.html' title='Gran Turismo 5 (eventually, I&apos;m assuming)'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-9013631925489983792</id><published>2011-06-25T15:07:00.001-07:00</published><updated>2011-06-25T15:32:20.902-07:00</updated><title type='text'>Console Gaming, Rebooted</title><content type='html'>I've become a bit disillusioned with console gaming over the past few years.  Many hours of my late teens were spent on the original PlayStation on classics like Final Fantasy VII &amp; VIII and the various incarnations of Resident Evil.  The upgrade to the PlayStation 2 in my early twenties was a foregone conclusion, offering much the same experience, but with better graphics and DVD playback as an added bonus.  But the PS3 has never quite captured me in the same way.  Part of that is undoubtedly me simply getting older. I'm married, have a daughter, and run my own consultancy company: it's only natural that some of the less important things like computer games slip a bit.&lt;br /&gt;&lt;br /&gt;Still, throughout each generation of console, I've always had at least a background flirtation with PC games.  Some games (first person shooters springing immediately to mind) are just out-and-out &lt;em&gt;better&lt;/em&gt; on a PC.  Something a simple as mouse vs. control pad become critically important when you want to be able to turn quickly to find out what's shooting you.  Other games (RPGs like Dragon age) are again just better on a PC largely because navigating the intricate menu systems of such games with a d-pad is infuriatingly slow.  Thus, while games like Infamous and God of War 3 on the PS3 are undoubtedly best on their home platforms, the shiny black console spent most of its time languishing unused under the TV, while its forgotten dad, the PS2, was in a damp-proof box with its games in the attic.&lt;br /&gt;&lt;br /&gt;Anyway, I bought a new &lt;a href="http://www.amazon.co.uk/gp/product/B001NEI7E8/ref=oss_product"&gt;monitor/TV&lt;/a&gt; earlier this week: finally time to retire the 4:3, 1280x1024 and catch up with the 1920x1080 high-def kids.  One of the major selling points for this particular monitor was the sheer number of connectivity offerings on its back.  My PC displays via DVI; I have a small, VIA-based server that has a VGA port for the occasional time (i.e. backups) when I need local terminal access; and there's an HDMI port for the aforementioned PS3.  But there's also component input, which made me think of the old PS2.  Indeed, why not hook both it and the PS3 up to the same display, just for kicks?&lt;br /&gt;&lt;br /&gt;Well, since I've done that, I've played the PS2 more than its younger, more powerful offspring, and it's reminded me of why console gaming used to be fun: it was just so &lt;em&gt;simple&lt;/em&gt;.  Shove in the disk, and go.&lt;br /&gt;&lt;br /&gt;With the PS3, turning it on assaults you with a menu of menus, each of which contains a dizzying number of options.  If you're an infrequent player like me, it seems like you're being prompted for a firmware update just about every time you turn the damn thing on, and if you play a game that you've not touched in a while, there's every possibility that you'll be looking at anything been 100MB and 1GB of patches to fix the problems caused by rushing the original version out the door.&lt;br /&gt;&lt;br /&gt;One of the great things about the PS1 and PS2 is that they didn't have internet connectivity, so game studios had to be very, very sure that the software they committed to CD or DVD was as bug free as possible.  With the PS3 (and Xbox360&amp;mdash;don't think I'm picking on the PS3 in particular), just about any old crap can be thrown together, to be patched later when the early adopters&amp;mdash;devoted fans that a studio should treat &lt;em&gt;especially&lt;/em&gt; well&amp;mdash;are used as unpaid acceptance testers.&lt;br /&gt;&lt;br /&gt;So I'm holding off on purchasing Infamous 2 for the PS3, and instead having fun with Shadow of the Colossus on the PS2.  I think I should be able to get through that and Silent Hill 2 before I see if I can stomach the hassles of modern console gaming, or whether I just ditch the platform and stick to the PC.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-9013631925489983792?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/9013631925489983792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2011/06/console-gaming-rebooted.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/9013631925489983792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/9013631925489983792'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2011/06/console-gaming-rebooted.html' title='Console Gaming, Rebooted'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8216255546009774330</id><published>2011-03-10T09:50:00.000-08:00</published><updated>2011-03-10T10:02:24.490-08:00</updated><title type='text'>Continuously Learning Lisp</title><content type='html'>I like to think that I 'know' Perl.  I also 'know' C, Java, Smalltalk, Ruby and a handful of other languages.  But Lisp is the only one that continually makes me feel like a newbie.  Just when you think you've got it pegged... BLAM&amp;mdash; you read something that shows you a completely new dimension.&lt;br /&gt;&lt;br /&gt;A good example of this for me is Nikodemus Siivola's post on &lt;a href="http://random-state.net/log/3507968044.html"&gt;"Optimizing Lookup Functions Using LOAD-TIME-VALUE"&lt;/a&gt;, basically demonstrating a way of altering the language such that hash table lookups with keys that are known to be constant at compile time have &lt;em&gt;no&lt;/em&gt; lookup overhead at runtime.&lt;br /&gt;&lt;br /&gt;I feel like I have a whole lot to learn, and it's good :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8216255546009774330?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8216255546009774330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2011/03/continuously-learning-lisp.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8216255546009774330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8216255546009774330'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2011/03/continuously-learning-lisp.html' title='Continuously Learning Lisp'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-4149635904700007249</id><published>2010-11-22T10:36:00.001-08:00</published><updated>2010-11-22T10:36:51.831-08:00</updated><title type='text'>Apple device fragmentation</title><content type='html'>Apple's Steve Jobs went on an &lt;a href="http://www.businessinsider.com/steve-jobs-epic-5-minute-anti-google-rant-2010-10"&gt;anti-Android rant&lt;/a&gt; earlier this year, focussing in particular on market fragmentation.  Apparently, there are so many configurations of Android device that it's writing software for the platform is next to impossible.  This came as a surprise to &lt;a href="http://androidheadlines.com/2010/10/tweetdecks-ceo-contradicts-steve-jobs-on-android-fragmentation.html"&gt;people who actually develop for it&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Apple, on the other hand, dodge the issue of fragmentation completely.  iOS is a completely unified platform, with only one catch: you must be up-to-date with the latest shiny toys.  The new &lt;a href="http://www.apple.com/pr/library/2010/11/22ios.html"&gt;iOS 4.2 is now available&lt;/a&gt;, with the following small caveat:&lt;br /&gt;&lt;br /&gt;&lt;div class="quotation"&gt;&lt;br /&gt;Availability&lt;br /&gt;&lt;br /&gt;The iOS 4.2 update is available today to download to iPad, iPhone and iPod touch by syncing the device with iTunes 10.1. iOS 4.2 is compatible with iPad, iPhone 3G, iPhone 3GS, iPhone 4, second and third generation iPod touch (late 2009 models with 32GB or 64GB) and new iPod touch. Some features may not be available on all products. For example, Multitasking requires iPhone 3GS, iPhone 4, third generation iPod touch (late 2009 models with 32GB or 64GB) or later. &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So, as with recent OS updates, it won't work with my first generation iPod Touch (or second gens, for that matter).  Owners of those devices are left with older versions of iOS, with no upgrade path that doesn't require a hardware purchase.&lt;br /&gt;&lt;br /&gt;Meaning that, if you're an application developer looking to target the broadest user base, you're hit with platform fragmentation...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-4149635904700007249?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/4149635904700007249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/11/apple-device-fragmentation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4149635904700007249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4149635904700007249'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/11/apple-device-fragmentation.html' title='Apple device fragmentation'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-5536357189871271889</id><published>2010-11-21T04:31:00.001-08:00</published><updated>2010-11-21T04:31:04.279-08:00</updated><title type='text'>Apple's 'Restart your computer' U-Turn</title><content type='html'>Once upon a time, Mac users could chuckle heartily at Windows users.  After every Windows Update, you'd get that prompt to restart your computer, and it was annoying.  If you're the kind of person who thinks that computers should serve rather than be served, you've probably got about a half dozen or more applications open, each containing reference material or partially completed work.&lt;br /&gt;&lt;br /&gt;Damn, those restarts were annoying.&lt;br /&gt;&lt;br /&gt;However, it's almost every other week that there's some update to Quicktime, Safari or iTunes, each adding more features that I don't care about (&lt;a href="http://www.apple.com/itunes/ping/"&gt;Ping&lt;/a&gt;?  Yet another social network, but one that's only accessible via the locked-down iTunes ecosystem?  Seriously..?)  I don't need my iTunes to support the latest devices from Apple: I haven't bought anything from them since my first-generation iPod touch (which still works superbly, by the way: I have no intentions of replacing it).&lt;br /&gt;&lt;br /&gt;Going back to that 'once upon a time', apps used to run &lt;em&gt;on top&lt;/em&gt; of Mac OS.  Now, Apple does what got Microsoft into so much hot water at the turn of the millennium: integrating home-grown apps into the operating system (otherwise known as 'gaining unfair advantage over competitors').  So, after updating to Mac OS 10.6.5 and restarting (ok, operating system updates &lt;em&gt;require&lt;/em&gt; restarts), I find that iTunes and Safari are both needing updated, also nagging for a restart.&lt;br /&gt;&lt;br /&gt;Well done, Apple.  You are the new Microsoft.  Enjoy the bubble.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-5536357189871271889?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/5536357189871271889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/11/apple-your-computer-u-turn.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5536357189871271889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5536357189871271889'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/11/apple-your-computer-u-turn.html' title='Apple&amp;#39;s &amp;#39;Restart your computer&amp;#39; U-Turn'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-5774113960720077948</id><published>2010-10-30T01:36:00.000-07:00</published><updated>2010-10-30T02:30:28.074-07:00</updated><title type='text'>The Ultimate Programmers' Keyboard</title><content type='html'>A professional in any craft needs quality tools, and for a computer programmer, the primary interface between the human and the computer is the keyboard.  End users of mass market software may be convinced that touch screen devices are the way forward, but for a programmer, nothing looks to be a serious threat to keyboards in the near to mid future.&lt;br /&gt;&lt;br /&gt;A quick &lt;a href="http://www.google.co.uk/#sclient=psy&amp;hl=en&amp;q=best+programmer+keyboard&amp;aq=f&amp;aqi=&amp;aql=&amp;oq=&amp;gs_rfai=&amp;pbx=1&amp;fp=3dd9e71350957573"&gt;google for 'best programmer keyboard'&lt;/a&gt; turns up the prime candidates: the &lt;a href="http://www.microsoft.com/hardware/mouseandkeyboard/productdetails.aspx?pid=043"&gt;Microsoft Ergonomic 4000&lt;/a&gt;; &lt;a href="http://www.daskeyboard.com/"&gt;das keyboard&lt;/a&gt;; the &lt;a href="http://en.wikipedia.org/wiki/Model_M_keyboard"&gt;IBM Model M&lt;/a&gt;; and the uniquely shaped &lt;a href="http://www.kinesis-ergo.com/"&gt;keyboards from Kinesis&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.logitech.com/en-us/keyboards/keyboard/devices/3498"&gt;Logitech G15&lt;/a&gt; seems to be popular among high-end users, but it's primarily a gaming keyboard, so I'm not including it here.&lt;br /&gt;&lt;br /&gt;My requirements are pretty simple:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;it must be durable and sturdy&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;it must be amenable to team-based working&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;and&amp;mdash;most importantly&amp;mdash;it must have a standard UK layout, with absolutely no dicking around with the positions of keys that are important to programmers, including the hash key (&amp;#35;, to the left of the large Enter key, shared with &amp;#126;), the back-quote (&amp;#8216;, top-left key on the main key cluster) and the pipe (&amp;#124;, shared with the backslash, between left-shift and the Z key)&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Anything from Apple is right out.  Even on their 'UK' keyboards, the double-quote (&amp;quot;) is where the &amp;#64; should be, and vice-versa. &lt;br /&gt;&lt;br /&gt;I immediately ruled out anything with the &lt;a href="http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard"&gt;Dvorak layout&lt;/a&gt;.  Yes, I'm familiar with the statistics about how it's a superior layout for computers, but it's simply not widespread enough for point 2.  I have a colleague on my current contract who has a &lt;a href="http://www.typematrix.com/"&gt;typematrix Dvorak keyboard&lt;/a&gt;, and he's very happy with it, but when it comes to a paired session or showing how to do something, it's a total pain.  The fastest way to get anything done is leave all the typing to him.&lt;br /&gt;&lt;br /&gt;Partly for point 2, I also ruled out anything with an extreme ergonomic layout (basically anything from Kinesis).  Also, while less-deformed ergonomic keyboards are good for a single user typing for a long time, paired programming is often about quickly shoving the keyboard over to a partner or grabbing it briefly to type a few lines, and ergonomic keyboards are obviously designed for someone sitting directly in front of them.  It's like you have to re-align yourself at the beginning of every switchover, which I find interrupts the flow.&lt;br /&gt;&lt;br /&gt;So, from my original list, I'm left with the Model M and Das Keyboard, both distinctly traditional in their non-ergonomics.  But then, from a front-page review endorsement on their &lt;em&gt;own website&lt;/em&gt;, &lt;cite&gt;"Das Keyboard compares to the legendary IBM Model M."&lt;/cite&gt;  So, which to go for?  The imitation or the original?&lt;br /&gt;&lt;br /&gt;Unsurprisingly, I'm typing this blog entry on my Model M.  The sticker on the bottom dates it from  1991, made in Greenock, Scotland&amp;mdash;about a half-hour's drive from where I live.  It's got all its key caps, has that satisfying two-stage click for each key press, and is solid enough to be used as a not-insignificant weapon if anyone breaks into my house.&lt;br /&gt;&lt;br /&gt;I simply can't find a better keyboard anywhere, and I'm beginning to think that there isn't one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-5774113960720077948?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/5774113960720077948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/10/ultimate-keyboard.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5774113960720077948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5774113960720077948'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/10/ultimate-keyboard.html' title='The Ultimate Programmers&apos; Keyboard'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-600241964666854786</id><published>2010-09-26T01:15:00.001-07:00</published><updated>2010-09-26T01:15:48.749-07:00</updated><title type='text'>More Homophobic Lunacy from the Catholic Church</title><content type='html'>&lt;div class="quotation"&gt;&lt;br /&gt;"I admire the gays and lesbians. They're small in number. But they're well-organised."&lt;br /&gt;&lt;br /&gt;"They've persuaded our legislators that the supreme moral values of the day are freedom and equality. Well they're not."&lt;br /&gt;&lt;br /&gt;"The supreme moral values are truth and goodness, and if you forget that, you end up with the mess we're in today."&lt;br /&gt;&lt;div class="quoter"&gt;Bishop of Motherwell, Joseph Devine, in an &lt;a href="http://news.bbc.co.uk/1/hi/programmes/from_our_own_correspondent/9031680.stm"&gt;interview with the BBC&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Once again, we see the catholic persecution complex in action: they're being systematically attacked by a 'well organised' group.  It's as though the church thinks that there's some kind of gay hierarchy, with lay-gays, event-organising gays and maybe even leader-gays, all plotting against the church and its bronze age values.&lt;br /&gt;&lt;br /&gt;Bollocks.&lt;br /&gt;&lt;br /&gt;There is simply a group of people who have human rights, voting power and a voice, qualities the church has traditionally abhorred.&lt;br /&gt;&lt;br /&gt;And isn't it convenient that the moral values of the day are unquantifiable and subject to varying definition?  There's little ambiguity about freedom and equality; it's obvious when one is being stomped on.  But 'truth' and 'goodness'?  The church defines what those are for its members, freeing them from the need to think about them, to make their own decisions.  Because that's the last thing the church needs its people doing&amp;mdash;&lt;em&gt;thinking&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;And why, when asked "can a loving relationship between two people of the same sex not be true and good?"&lt;br /&gt;&lt;br /&gt;"Because it's not creative".&lt;br /&gt;&lt;br /&gt;I'm assuming that he means pro-creative here, not just generally creative: the love shared between two people of the same sex is on even par with any other, and is creative in way that it enriches their lives and the lives of those around them.  But he's right, it's not &lt;em&gt;pro&lt;/em&gt;-creative: it doesn't bring new life into the world.  But then, neither does a heterosexual marriage where one side or the other is sterile&amp;mdash;does he propose nullifying such marriages, tearing such couples apart?  Surely if &lt;em&gt;one&lt;/em&gt; of them is capable of reproduction, it's a sin against god and humanity if that person doesn't find a fertile mate?&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-600241964666854786?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/600241964666854786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/09/more-homophobic-lunacy-from-catholic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/600241964666854786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/600241964666854786'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/09/more-homophobic-lunacy-from-catholic.html' title='More Homophobic Lunacy from the Catholic Church'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8170196865097944995</id><published>2010-09-19T09:54:00.001-07:00</published><updated>2010-09-19T10:51:17.387-07:00</updated><title type='text'>Crazy Proselytising</title><content type='html'>There were a few street preachers in Argyle Street in Glasgow today.  You know, the ones who brandish a bible and shout loudly about how &lt;em&gt;you&lt;/em&gt; can be &lt;em&gt;saved&lt;/em&gt;.  The lead of the small group&amp;mdash;a surprisingly young looking gentleman&amp;mdash;was busy proclaiming how morally corrupt society is today, filled as it is by people who live by the creed of "if it feels good and no one gets hurt, then it's ok".  While I was puzzling over exactly what the problem with that viewpoint is, he continued that we should return to the "moral certainty of the old days".&lt;br /&gt;&lt;br /&gt;Would those be the days when we stoned people for disobedience, I wonder?  Burned them at the stake for witchcraft?  Or seared them with irons for blasphemy?&lt;br /&gt;&lt;br /&gt;Throughout all this, the placard by his side read:&lt;br /&gt;&lt;br /&gt;&lt;div class="quotation"&gt;I am the way and the truth and the life. No one comes to the Father except through me &amp;mdash; John 14:6&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This passage, more than just about any other in the bible, highlights the "we're right, everyone else is wrong" mentality of Christianity that belies talk of unity with other religions.&lt;br /&gt;&lt;br /&gt;I could only chuckle as I walked past.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8170196865097944995?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8170196865097944995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/09/crazy-proselytising.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8170196865097944995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8170196865097944995'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/09/crazy-proselytising.html' title='Crazy Proselytising'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-2790149022360952665</id><published>2010-09-17T11:20:00.000-07:00</published><updated>2010-09-19T02:56:08.171-07:00</updated><title type='text'>The Pope Slanders Free Thinkers</title><content type='html'>&lt;style type="text/css"&gt;div.quotation { margin-right: 3em; margin-left: 3em; padding: 1em; background-color: #eee; }&lt;/style&gt;&lt;p&gt;The Pope was in my nearest city of Glasgow yesterday, offering his sermon in Bellahouston Park, just south of the River Clyde.  His message was at once one of optimistic hope for his faithful flock and an out-and-out slanderous attack against the largely secular, non-theistic people of the UK.&lt;/p&gt;&lt;div class="quotation"&gt;&lt;cite&gt;Even in our own lifetimes we can recall how Britain and her leaders stood against a Nazi tyranny that wished to eradicate God from society and denied our common humanity to many, especially the Jews, who were thought unfit to live.As we reflect on the sobering lessons of atheist extremism of the 20th century, let us never forget how the exclusion of God, religion and virtue from public life leads ultimately to a truncated vision of man and of society and thus a reductive vision of a person and his destiny.&lt;/cite&gt;&lt;div align="right"&gt;&lt;em&gt;Pope Benedict XVI, Bellahouston Park, Glasgow, 16-Sep-2010&lt;/em&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Umm... excuse me?  Hitler was a Catholic.  The Catholic church, while refusing to back the Nazi party of Germany, similarly refused to condemn it.  Hitler's attack was against the entire Jewish race, not entirely unmotivated by the church's own hatred of the race thanks to the &lt;a href="http://en.wikipedia.org/wiki/Jewish_deicide"&gt;charge of decide&lt;/a&gt; that was only lifted in the 1960s (which has always slightly confused me: if Jesus's defining sacrifice is what frees us all from sin, surely he &lt;em&gt;had to die&lt;/em&gt; in order to rise, ascend into heaven, etc.).&lt;/p&gt;&lt;p&gt;"Oh, no", whine the apologists. "Hitler wasn't Catholic.  He just used religion to control the people".  Is that so?  Well, in order to control the people with religion, what religion would those people have to follow? So, given that Hitler didn't personally murder millions of Jews,what's their excuse?&lt;/p&gt;&lt;p&gt;And how about this little gem from the megalomaniacal 'atheist' dictator?&lt;/p&gt;&lt;div class="quotation"&gt;&lt;cite&gt;The Government, being resolved to undertake the political and moral purification of our public life, are creating and securing the conditions necessary for a really profound revival of religious life&lt;/cite&gt;&lt;/p&gt;&lt;div align="right"&gt;&lt;em&gt;Adolf Hitler, in a speech to the Reichstag onMarch 23, 1933&lt;/em&gt;&lt;/div&gt;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;Do those sound like the words of an atheist to you?&lt;/p&gt;&lt;p&gt;Stepping away from the distortions of the past that the Pope seems to enjoy, we find that his view of the present is no less warped:&lt;/p&gt;&lt;div class="quotation"&gt;&lt;cite&gt;There are some who now seek to exclude religious belief from public discourse, to privatise it or even to paint it as a threat to equality and liberty. Yet religion is in fact a guarantee of authentic liberty and respect, leading us to look upon every person as a brother or sister.&lt;div align="right"&gt;&lt;em&gt;Pope Benedict XVI, Bellahouston Park, Glasgow, 16-Sep-2010&lt;/em&gt;&lt;/div&gt;&lt;/cite&gt;&lt;/div&gt;&lt;p&gt;Again... excuse me?  Doesn't the Catholic church tell us that women are not fit to be priests, and therefore cannot be part of the church's own heirarchy except at the lowest levels?  Doesn't it teach us that gays are abominations in the sight of god, and forever damned unless they 'repent' for making that 'choice'?  All this from a church that refuses even to discuss the possibility of ordaining women, forbidding it from being mentioned.&lt;/p&gt;&lt;p&gt;The church is an open &lt;em&gt;threat&lt;/em&gt; to liberty and respect, not its guardian.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-2790149022360952665?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/2790149022360952665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/09/pope-was-in-my-nearest-city-of-glasgow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2790149022360952665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2790149022360952665'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/09/pope-was-in-my-nearest-city-of-glasgow.html' title='The Pope Slanders Free Thinkers'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-5412949740340258028</id><published>2010-08-28T00:31:00.001-07:00</published><updated>2010-08-28T00:31:53.976-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>Online Stalking: it's not the ISPs Fault.</title><content type='html'>The BBC is &lt;a href="http://www.bbc.co.uk/news/uk-11118152"&gt;running an article&lt;/a&gt; about how ISPs are 'thwarting' a crackdown on online stalking.  Apparently, they should not only deliver Internet connectivity (their job), they should also police it (not their job).  It's like saying that the makers of paper should be responsible for what's written on it, or that the makers of envelopes should be responsible for what's delivered in them.&lt;br /&gt;&lt;br /&gt;Of course, what's barely mentioned is that you should be very careful about personal details that you post online.  Do NOT post details of your current location, places where you can often be found, your home address, your phone number, etc.  Doing so is just asking for trouble, and blaming the ISP&amp;mdash;even when social networking sites (still &lt;em&gt;not&lt;/em&gt; the ISP) encourage you to yield such information&amp;mdash;is equivalent to blaming manufacturers of junk food for &lt;em&gt;forcing&lt;/em&gt; you to eat rubbish by making appealing adverts.&lt;br /&gt;&lt;br /&gt;The &lt;em&gt;last&lt;/em&gt; thing we want is ISPs policing Internet access according to a private set of rules formed by a mob committee.  I'm even wary of the Law of the Land applying to the &lt;em&gt;delivery&lt;/em&gt; of content (the hosting is another matter).  It's a slippery slope when your government gets used to being able to filter content that it finds objectionable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-5412949740340258028?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/5412949740340258028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/online-stalking-it-not-isps-fault.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5412949740340258028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5412949740340258028'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/online-stalking-it-not-isps-fault.html' title='Online Stalking: it&amp;#39;s not the ISPs Fault.'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-2939394563162801122</id><published>2010-08-27T11:57:00.001-07:00</published><updated>2010-08-27T11:58:25.603-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='h264'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>h264 is not Free</title><content type='html'>With news of the sudden &lt;a href="http://arstechnica.com/media/news/2010/08/mpeg-la-counters-google-webm-with-permanent-royalty-moratorium.ars"&gt;royalty free amendment to the h264 license by the MPEG LA&lt;/a&gt; sweeping the web, it's easy to forget that this actually changes very little, indeed.  You now won't ever be charged for viewing free video on the Internet.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;You will &lt;em style="font-style: normal; text-transform: uppercase"&gt;still&lt;/em&gt; be charged for distributing an h264 encoder or decoder&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;This means that if you're someone like the &lt;a href="http://www.mozilla.org"&gt;Mozilla&lt;/a&gt; group, you can't include h264 support for the HTML5 &amp;lt;video&amp;gt; tag without paying hefty royalties for the privilege.  You might wonder what the problem is: surely it's right that one company licenses the right to distribute the technology of another?  No.  Not when it comes to the Web and the standards that underpin it (such as HTML5).  Paying a royalty to take part in the Web defeats the entire point of an open internet, where ideas can be freely exchanged using the promise that the base standards are available to everyone on a royalty-free basis.&lt;br /&gt;&lt;br /&gt;There's some sanity on this 'sweeping change' from the MPEG LA at &lt;a href="http://createdigitalmotion.com/2010/08/apple-centric-observers-get-the-facts-wrong-h-264-still-isnt-free-for-firefox/"&gt;Create Digital Motion&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;H264 is not the only codec out there.  You can distribute the encoders, decoders and content with WebM/VP8 and Ogg/Theora without restriction.&lt;br /&gt;&lt;br /&gt;Use 'em.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-2939394563162801122?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/2939394563162801122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/h264-is-free.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2939394563162801122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2939394563162801122'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/h264-is-free.html' title='h264 is &lt;em&gt;not&lt;/em&gt; Free'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-5636746297724076929</id><published>2010-08-25T07:06:00.001-07:00</published><updated>2010-08-25T07:06:40.504-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='family'/><category scheme='http://www.blogger.com/atom/ns#' term='catholicism'/><title type='text'>Being an Ex-Catholic Atheist at a Catholic Funeral</title><content type='html'>My gran died last Thursday.  At 88 years old and of frail health, her increasingly common mental lapses meant that it wasn't unexpected when it happened, but nothing quite prepares you for that phonecall.&lt;br /&gt;&lt;br /&gt;Her funeral was today, attended by the two generations behind her&amp;mdash;probably the best turnout at a family gathering for many years.  Religiously, my family is traditionally Catholic, at least in name.  We traditionally only see the inside of a church at funerals, with weddings being secular affairs and not much interest in baptising our children.  Still, if you were to ask my sisters, aunts, uncles or cousins what religious affiliation they belong to, it'd be Catholic.&lt;br /&gt;&lt;br /&gt;As far as I know, I'm the only openly declared atheist.  Before going on, the reason I left the church is simply because I couldn't reconcile my beliefs about how to live a good life with what I was reading and being taught.  I have no stories about abusive priests, psychological trauma induced by images of hell, or any of the stuff that commonly makes it into the Reasons to Hate the Catholic Church&amp;trade;.&lt;br /&gt;&lt;br /&gt;So the ceremony itself was a little weird.  Having gone through Catholic education, I knew exactly what to say at what times, and when to stand, sit or kneel.  It's slightly odd that I remembered the prayers: they must have been burned into my brain when I was a boy.&lt;br /&gt;&lt;br /&gt;But, aside from standing and sitting and that shaking of hangs thing they do prior to communion, I didn't &lt;em&gt;do&lt;/em&gt; any of it.  I didn't recite or respond to the prayers, sing hymns, bless myself with water, bow my head or press my hands together in front of me.  While the priest was asking people to honour god, I was instead remembering my gran.&lt;br /&gt;&lt;br /&gt;When I was paying attention to what the priest was saying, the thing that generally struck me was the occasional reminder that we're born sinners, achieving grace &lt;em&gt;only&lt;/em&gt; through Christ.  There was even a dig at non-believers in the reading from the book of 'Wisdom', where we are collectively labelled as 'fools' for believing that death is the end of a persons life.&lt;br /&gt;&lt;br /&gt;As a foolish non-believer, what I found very odd was the tinkling of bells by the altar boy when the priest blessed and raised the bread and wine, a process which&amp;mdash;according to believers&amp;mdash;transubstantiates them into the actual body of blood of Jesus Christ.  The communion itself seemed similarly strange, with people treating these little, mass-produced flecks of unleavened bread with such incredible solemnity.  Knowing that most of the congregation in front of him probably hadn't communed in years, and bearing in mind the Catholic no-no about taking communion with a sin-stained soul, the priest offered blessings to those who remembered enough of the dogma to stay away because of that.&lt;br /&gt;&lt;br /&gt;With with mass almost at its end, all that remained was to sprinkle 'holy' water over the coffin and wreath it with smoke from burning incense.  This done, the coffin was taken to the cemetery and interred alongside my granddad, laid to rest seventeen years earlier.&lt;br /&gt;&lt;br /&gt;After all this, what I'm most shocked with is myself.  For quite an extended period of time, I &lt;em&gt;believed&lt;/em&gt; this stuff.  I took part in the rites and rituals, saw value in the prayers and songs and material paraphernalia.  And it wasn't even that long ago: I was a practising Catholic up until about ten years ago, a lapsed one for about five years after that, finally moving on to agnosticism and finally atheism over the course of the following two or three years.  Not coincidentally, all of this happened alongside actually &lt;em&gt;reading&lt;/em&gt; the bible, learning about its origins, learning about other religions, and seeing the harm inflicted by the church thanks to its views on contraception, sex education, and homosexuals.&lt;br /&gt;&lt;br /&gt;How times change.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-5636746297724076929?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/5636746297724076929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/being-ex-catholic-atheist-at-catholic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5636746297724076929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5636746297724076929'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/being-ex-catholic-atheist-at-catholic.html' title='Being an Ex-Catholic Atheist at a Catholic Funeral'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-4085084489667892524</id><published>2010-08-21T07:02:00.001-07:00</published><updated>2010-08-25T06:06:41.628-07:00</updated><title type='text'>Net-Connected Consoles with Hard Drives Deliver Poor Quality Games</title><content type='html'>A while ago, I bought &lt;a href="http://www.unchartedthegame.com/U2AT/"&gt;Uncharted 2&lt;/a&gt; for the PS3.  Unfortunately, with the arrival of my daughter into the world, it was one of those titles that barely got loaded at first.&lt;br /&gt;&lt;br /&gt;Today, I put the disk into the console, and then BAM!, several hundred megabytes of updates are required before I can play the game.  It would appear that there have been one or two bugs in the shipped version.&lt;br /&gt;&lt;br /&gt;Which got me wondering: why, with the console's predecessors, was this never an issue?  The answer is kinda obvious: you've got a network, a hard drive and a very competitive market.  With previous generations of console, you had to make damn sure that what you burned onto that CD for shipping was a quality product.  Your update channel amounted to a return of the physical medium for a fixed copy.  Not very attractive.  Now, however, you can ship with any half-arsed, bug-ridden product and patch it later.&lt;br /&gt;&lt;br /&gt;One thing that console games used to have over their PC siblings was that they &lt;em&gt;just worked&lt;/em&gt;.  Stick the disk in and go.  No configuring audio and video drivers, no checking the specs of your machine against the overly optimistic listings on the side of the box (only to find out that the screen shots on the packaging must have been taken from some next-generation video hardware), and &lt;em&gt;no patching shoddy software with updates to fix problems that should never have made it through testing&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;EDIT: apparently, a couple of hundred megabytes of patches aren't enough.  It took only a half hour of playing (in the raid on the museum in Instanbul) to be bitten by this glitch:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align:center;"&gt;&lt;img src="http://lh4.ggpht.com/_woBmp3G-OW8/TG_n47FlwjI/AAAAAAAAAFU/ZVfyAEYSW9M/uc2-bug.jpg?imgmax=800" alt="uc2-bug.jpg" border="0" width="640" height="403" /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-4085084489667892524?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/4085084489667892524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/net-connected-consoles-with-hard-drives.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4085084489667892524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4085084489667892524'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/net-connected-consoles-with-hard-drives.html' title='Net-Connected Consoles with Hard Drives Deliver Poor Quality Games'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_woBmp3G-OW8/TG_n47FlwjI/AAAAAAAAAFU/ZVfyAEYSW9M/s72-c/uc2-bug.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-7183858769685542266</id><published>2010-08-01T02:45:00.001-07:00</published><updated>2010-08-03T12:45:05.978-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='mencoder'/><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='ipod'/><title type='text'>Encoding x264 Video for the iPod Touch with mencoder</title><content type='html'>I tend to view a lot of video content on my first-generation iPod Touch.  It's great for travelling, with its these-days-paltry 16GB capacity able to store well over a dozen half hour episodes of whatever I'm following at the time.&lt;br /&gt;&lt;br /&gt;While there are some wonderful graphical encoders out there (&lt;a href="http://handbrake.fr/"&gt;HandBrake&lt;/a&gt; springs to mind), what I was looking for was something I could script.  I know that HandBrake has a &lt;a href="https://trac.handbrake.fr/wiki/CLIGuide"&gt;command line interface&lt;/a&gt;, but I prefer &lt;a href="http://www.mplayerhq.hu/design7/news.html"&gt;mencoder&lt;/a&gt;'s support for embedded subtitle streams, which is something I use often.&lt;br /&gt;&lt;br /&gt;If you're on a fairly recent SVN of mplayer (say &amp;gt;= r31363), you'll find that mencoder now supports a &lt;code&gt;profile&lt;/code&gt; in &lt;code&gt;x264encopts&lt;/code&gt;.  &lt;strong&gt;This is important!&lt;/strong&gt;  The default is &lt;em&gt;high&lt;/em&gt;, which the &lt;a href="http://www.apple.com/ipodtouch/specs.html"&gt;iPod explicitly doesn't support&lt;/a&gt;.  What you need is &lt;em&gt;baseline&lt;/em&gt;, leading to something like this:&lt;br /&gt;&lt;br /&gt;&lt;style&gt;&lt;br /&gt;td { border-bottom: 1px solid black }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tr&gt;&lt;td colspan="3"&gt;mencoder INPUT-FILE -o OUTPUT_FILE&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-vf scale=480:-10,harddup&lt;/td&gt;&lt;td&gt;# resize the video to whichever height is suitable for the max 480px width&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-sws 9&lt;/td&gt;&lt;td&gt;# Choose a really good scaler (lanczos)&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-of lavf&lt;/td&gt;&lt;td&gt;# use lavf for output&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-lavfopts format=mp4&lt;/td&gt;&lt;td&gt;# specifically, mp4&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-oac faac&lt;/td&gt;&lt;td&gt;# AAC audio for output&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-faacopts mpeg=4:object=2:raw:br=128&lt;/td&gt;&lt;td&gt;# Audio coding parmeters&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-mc 0 -noskip&lt;/td&gt;&lt;td&gt;# Really work at keeping A/V sync&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-ovc x264&lt;/td&gt;&lt;td&gt;# x264 video&lt;/td&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-x264encopts nocabac: bframes=0: level_idc=30: global_header: threads=auto: subq=5: frameref=6: partitions=all: trellis=1: chroma_me: me=umh: bitrate=768: &lt;strong&gt;profile=baseline&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Video coding parameters.  Note the &lt;strong&gt;baseline&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-aid 0 -sid 0&lt;/td&gt;&lt;td&gt;# Audio and subtitle tracks&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;-subfont-text-scale 4&lt;/td&gt;&lt;td&gt;# Better subtitle scaling for an iPod sized device&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(or, for a more cut n' paste friendly version:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;mencoder INPUT-FILE -o OUTPUT-FILE -vf scale=480:-10,harddup -sws 9 -of lavf -lavfopts format=mp4 -oac faac -faacopts mpeg=4:object=2:raw:br=128 -mc 0 -noskip -ovc x264 -x264encopts nocabac:level_idc=30:bframes=0:global_header:threads=auto:subq=5:frameref=6:partitions=all:trellis=1:chroma_me:me=umh:bitrate=768:profile=baseline -aid 0 -sid 0 -subfont-text-scale 4&lt;/code&gt;)&lt;br /&gt;&lt;br /&gt;This transcodes the source in a single pass.  Lots of people strongly advocate two-pass encoding, but really, I find the quality of a single pass encode good enough for the iPod screen.  There's no denying that two-pass is higher quality, but the extra time to encode disposable content just isn't worth it in my opinion.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-7183858769685542266?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/7183858769685542266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/encoding-x264-video-for-ipod-touch-with.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7183858769685542266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7183858769685542266'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/08/encoding-x264-video-for-ipod-touch-with.html' title='Encoding x264 Video for the iPod Touch with mencoder'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-51415105658384416</id><published>2010-06-05T13:43:00.000-07:00</published><updated>2010-06-05T13:59:39.313-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firmware'/><category scheme='http://www.blogger.com/atom/ns#' term='DG834G'/><category scheme='http://www.blogger.com/atom/ns#' term='netgear'/><category scheme='http://www.blogger.com/atom/ns#' term='wireless'/><category scheme='http://www.blogger.com/atom/ns#' term='1.03.22'/><title type='text'>Netgear's Broken Firmwares</title><content type='html'>I bought a Netgear DG834G from &lt;a href="http://www.amazon.co.uk"&gt;Amazon&lt;/a&gt; earlier this week.  It arrived on Friday, and promptly replaced the crash-tastic BT Home Hub that preceded it.  Having been using Netgear products for years, I quickly set up and secured my wireless LAN, made a couple of DHCP reservations for servers on my home network, forwarded ports for various services from the Internet to those servers, hooked up to my &lt;a href="http://www.dyndns.org"&gt;DynDNS&lt;/a&gt; account, and was content.  Then I noticed that the forwarded ports weren't forwarding: my web and mail servers were inaccessible.  Much tinkering later, and I decide that the unit is defective, and arrange to return it to Amazon (who, it must be said, have a superbly streamlined returns process).&lt;br /&gt;&lt;br /&gt;But I still didn't want to go back to the BT Home Hub&amp;mdash;the frequent crashes were just too frustrating.  So I dig out an old Netgear router that I found in The Pile in the bits n' pieces cupboard, and find that it still works.  And hey, port forwarding even works!&lt;br /&gt;&lt;br /&gt;Feeling good about it, I let the old kit do its thing, stable and reliable.  So why not treat it to a firmware upgrade?  I grab the latest (v1.03.22) from &lt;a href="http://kb.netgear.com/app/products/model/a_id/2328"&gt;the Netgear product page&lt;/a&gt;, re-flash the unit, &lt;em&gt;and port forwarding stops working!&lt;/em&gt;  Crawling around some forums, I find that &lt;a href="http://forum1.netgear.com/showthread.php?t=50568"&gt;I'm not alone&lt;/a&gt;.  It would appear that Netgear have broken something as fundamental as port forwarding in their recent firmwares!&lt;br /&gt;&lt;br /&gt;Incredulous, I download v1.02.19.  Still doesn't work (and almost bricks my unit in the re-flashing process).  By now more than a little annoyed, I resort to v1.02.13, which I &lt;em&gt;think&lt;/em&gt; was the original version.  And you know what?  It works.&lt;br /&gt;&lt;br /&gt;Not all upgrades are upgrades, it would seem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-51415105658384416?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/51415105658384416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/06/netgears-broken-firmwares.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/51415105658384416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/51415105658384416'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/06/netgears-broken-firmwares.html' title='Netgear&apos;s Broken Firmwares'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-4761576054080694794</id><published>2010-05-05T05:45:00.000-07:00</published><updated>2010-05-05T05:52:56.664-07:00</updated><title type='text'>h264 shenanigans</title><content type='html'>&lt;a href="http://www.engadget.com/"&gt;Engadget&lt;/a&gt; has an &lt;a href="http://www.engadget.com/2010/05/04/know-your-rights-h-264-patent-licensing-and-you"&gt;excellent article&lt;/a&gt; that attempts to clarify the muddy waters of licensing and patents surrounding the h264 video codec. One of the snippets from the article, important enough that they list it in a side-box, is &lt;cite&gt;"using H.264 to distribute free internet video to end users doesn't cost a thing, and won't cost anything until at least 2015. After that, it's up in the air, and that's a bridge we'll have to cross when we come to it &amp;mdash; there's a chance the MPEG-LA could start charging a royalty for free video in five years."&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;Two parts of that sentence should cause any sane person cause for concern:&lt;br /&gt;&lt;br /&gt;&lt;dl&gt;&lt;br /&gt;&lt;dt&gt;...won't cost anything until at least 2015.&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;That's only five years away.  Just enough time to generate an awful lot of content that would take a lot of effort to get away from.&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;After that, it's up in the air...&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;That's not exactly something to be happy about.  There's no point making extensive use on h264 and then hoping that it'll turn out ok, especially when there are perfectly workable alternatives.&lt;/dd&gt;&lt;br /&gt;&lt;/dl&gt;&lt;br /&gt;&lt;br /&gt;The article does do a good job of dispelling a lot of the scaremongering that's been going on, but what's left is still distinctly unpleasant.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-4761576054080694794?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/4761576054080694794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/05/h264-shenanigans.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4761576054080694794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4761576054080694794'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/05/h264-shenanigans.html' title='h264 shenanigans'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-3613476523325147488</id><published>2010-05-04T02:43:00.000-07:00</published><updated>2010-05-04T02:49:27.325-07:00</updated><title type='text'>Labour Promote Political Sabotage</title><content type='html'>Now that it's blindingly obvious that the UK Labour Party is going to lose the General Election later this week, they've resorted to &lt;a href="http://news.bbc.co.uk/1/hi/uk_politics/election_2010/8658694.stm"&gt;abusing the voting system&lt;/a&gt; in order to prevent their long term rivals, the Conservatives, from winning a complete victory.  In areas where the Liberal Democrats are a larger threat to the Tories than Labour themselves, the advice is to vote Lib Dem in order to prevent them gaining the seat.&lt;br /&gt;&lt;br /&gt;Does anyone else think that the system is broken?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-3613476523325147488?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/3613476523325147488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/05/labour-promote-political-sabotage.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/3613476523325147488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/3613476523325147488'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/05/labour-promote-political-sabotage.html' title='Labour Promote Political Sabotage'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-6049870276275209493</id><published>2010-05-02T06:01:00.001-07:00</published><updated>2010-05-03T04:24:19.142-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Apple's vision of an 'open' web</title><content type='html'>Apple are certainly 'thinking different' when it comes to the definition of 'open'.  In their spat with Adobe regarding Flash on Apple's mobile products, Steve Jobs responded &lt;a href="http://www.apple.com/hotnews/thoughts-on-flash/"&gt;almost convincingly&lt;/a&gt; about why Flash isn't on the Apple mobile product line.  The primary reason?  Openness.  Flash is a closed platform, whereas JavaScript, CSS and HTML 5 are all open.&lt;br /&gt;&lt;br /&gt;The 'but' here comes from the HTML 5 part, which includes a &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; tag that essentially renders Flash video obsolete, with decode and render available natively in the browser, rather than through a plugin.  The standards committee overseeing HTML 5 still hasn't agreed on what &lt;em&gt;format&lt;/em&gt; that video should be delivered in.  The de-facto standard of &lt;a href="http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC"&gt;h264&lt;/a&gt;, a high-quality, industry-driven standard that's nevertheless mired in patent and licensing issues that are &lt;a href="http://www.fsf.org/licensing/h264-patent-license"&gt;really sticky&lt;/a&gt;.  Or &lt;a href="http://xiph.org"&gt;Xiph's&lt;/a&gt; &lt;a href="http://www.theora.org/"&gt;Theora&lt;/a&gt;, which has been designed to avoid using techniques covered by patents, and is available royalty-free (which most of us think of when we think 'free').&lt;br /&gt;&lt;br /&gt;When it comes to browser support, &lt;a href="http://www.microsoft.com" title="Microsoft"&gt;the&lt;/a&gt; &lt;a href="http://www.apple.com" title="Apple"&gt;big&lt;/a&gt; &lt;a href="http://www.google.com" title="Google"&gt;three&lt;/a&gt; unsurprisingly lend their weight to h264.  Mozilla's &lt;a href="http://www.firefox.com"&gt;Firefox&lt;/a&gt;&amp;mdash;distinct from the others in being the only organisation that's an actual &lt;em&gt;browser&lt;/em&gt; company and also non-profit&amp;mdash;throws its weight behind Theora, with that crazy idea that participating in the web shouldn't involve licensing fees just to &lt;em&gt;access&lt;/em&gt; it.&lt;br /&gt;&lt;br /&gt;Of the corporations, Google has interestingly &lt;a href="http://www.webmonkey.com/2010/04/report-google-will-release-vp8-video-codec-under-an-open-source-license/"&gt;promised to open source the VP8 codec&lt;/a&gt; and, since they own &lt;a href="http://www.youtube.com"&gt;YouTube&lt;/a&gt;, could theoretically swing the balance by offering VP8 support in Chrome and VP8 YouTube videos, especially if Firefox supported the same.&lt;br /&gt;&lt;br /&gt;But, back to Apple.&lt;br /&gt;&lt;br /&gt;Steve Jobs reckons that &lt;a href="http://blogs.fsfe.org/hugo/2010/04/open-letter-to-steve-jobs/comment-page-1/#sjobs"&gt;there's no such thing as a free video codec&lt;/a&gt;.  Furthermore, he issues a threat to Xiph over Theora (without including useful specifics, which relegates it to FUD).&lt;br /&gt;&lt;br /&gt;So Steve: get a grip.  The i-whatever ecosystem is locked down tight, and you're free to do that to whatever extent your customers are willing to put up with, but don't hide behind a wall of righteousness when dissing other technologies.  Your 'open' arguments are empty with a platform and environment that is &lt;a href="http://daringfireball.net/2010/04/why_apple_changed_section_331"&gt;increasingly developer hostile&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As for me, I've owned a G4 PowerBook and am typing this on a two year old Macbook Pro. With each statement from Jobs regarding criticism of his closed platform, I find it increasingly unlikely that I'll buy a third.  So hey, Apple marketing-types: your CEO's statements are costing you a &amp;#163;1500 sale, and most likely not just from me.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Edit:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Apparently &lt;a href="http://xml.coverpages.org/AppleComputerPatentStatement.html"&gt;Apple once believed in a royalty-free Web&lt;/a&gt;, too.  However, despite the original having lived &lt;a href="http://www.apple.com/about/w3c/"&gt;here on apple.com&lt;/a&gt; for years, it's recently been pulled.&lt;br /&gt;&lt;br /&gt;Thankfully, George Orwell's &lt;a href="http://en.wikipedia.org/wiki/Memory_hole"&gt;Memory Holes&lt;/a&gt; are a difficult thing to accomplish with an open Web.&lt;br /&gt;&lt;br /&gt;Hat-tip to &lt;a href="http://news.ycombinator.com/item?id=1314446"&gt;ZeroGravitas&lt;/a&gt; on &lt;a href="http://news.ycombinator.com"&gt;Hacker News&lt;/a&gt; for the info (and to Create on the comments page for the Memory Hole reference).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-6049870276275209493?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/6049870276275209493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/05/apple-vision-of-web.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/6049870276275209493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/6049870276275209493'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/05/apple-vision-of-web.html' title='Apple&amp;#39;s vision of an &amp;#39;open&amp;#39; web'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8327968938103016846</id><published>2010-04-08T12:35:00.001-07:00</published><updated>2010-04-09T03:42:59.151-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Simple File Renaming in Emacs</title><content type='html'>I stumbled across &lt;a href="http://blog.tuxicity.se/elisp/emacs/2010/03/26/rename-file-and-buffer-in-emacs.html"&gt;this tip&lt;/a&gt; while browsing &lt;a href="http://www.reddit.com/r/emacs"&gt;reddit/emacs&lt;/a&gt;.  In summary, it allows for the possibility of having a 'write file' (&lt;code&gt;C-x C-w&lt;/code&gt;) variant that deletes the original file, essentially performing a simple rename without having to invoke &lt;code&gt;dired&lt;/code&gt; or fire up a shell.&lt;br /&gt;&lt;br /&gt;Putting on my Emacs cap, I came up with something similar, shorter and (debatably) more 'emacs-y':&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size:smaller;"&gt;&lt;br /&gt;(defadvice write-file (around write-file-possibly-rename activate)&lt;br /&gt;  (let ((old-filename (buffer-file-name)))&lt;br /&gt;    ad-do-it&lt;br /&gt;    (and current-prefix-arg&lt;br /&gt;         old-filename&lt;br /&gt;         (not (string-equal old-filename (buffer-file-name)))&lt;br /&gt;         (delete-file old-filename))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;defadvice&lt;/code&gt; allows you to hook a new function up to an existing one, to be invoked either before, after or &lt;em&gt;around&lt;/em&gt; it (around advice invokes the original function with its original arguments with &lt;code&gt;ad-do-it&lt;/code&gt;, and can do that zero or more times).  This form of advice is what hits the spot for this task.  Subsequently, when &lt;code&gt;write-file&lt;/code&gt; is called, this advice intercepts it, captures the current filename and then invokes the old behaviour.  After the write has happened, it checks to see whether or not it should delete the old file, and does so if the preconditions are met.&lt;br /&gt;&lt;br /&gt;This preserves the existing &lt;code&gt;C-x C-w&lt;/code&gt; behaviour, creating a completely new copy of your file if you choose a different name.  Invoked as &lt;code&gt;C-u C-x C-w&lt;/code&gt;, however, it deletes the old filename, performing the same rename with less code and less duplication of the existing file-writing plumbing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8327968938103016846?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8327968938103016846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/04/simple-file-renaming-in-emacs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8327968938103016846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8327968938103016846'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/04/simple-file-renaming-in-emacs.html' title='Simple File Renaming in Emacs'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-7924356135023427851</id><published>2010-04-08T05:06:00.001-07:00</published><updated>2010-04-08T05:07:28.757-07:00</updated><title type='text'>Gordon's Pledges?</title><content type='html'>&lt;a href="http://www.timesonline.co.uk/tol/news/politics/article7091399.ece"&gt;Gordon Brown pledges 'five more years' as Prime Minister if Labour wins&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;That's not a pledge, Gordon.  That's a &lt;em&gt;threat&lt;/em&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-7924356135023427851?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/7924356135023427851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/04/gordons-pledges.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7924356135023427851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7924356135023427851'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/04/gordons-pledges.html' title='Gordon&apos;s Pledges?'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-1184207859503968130</id><published>2010-04-04T08:22:00.001-07:00</published><updated>2010-04-04T08:22:40.241-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='catholicism'/><title type='text'>Institutional Abuse is not "Petty Gossip"</title><content type='html'>&lt;a href="http://news.bbc.co.uk/1/hi/world/europe/8602644.stm"&gt;Cardinal Angelo Sodano has said the Roman Catholic faithful will not be swayed by "petty gossip" about child sex-abuse allegations&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I find myself stunned.&lt;br /&gt;&lt;br /&gt;The church faces far more than "petty gossip", at least as far as Giuseppe dalla Torre, head of the Vatican's tribunal, seems to be concerned, compelled as he was to remind us that &lt;a href="http://news.yahoo.com/s/nm/20100401/ts_nm/us_pope_abuse"&gt;the pope cannot be called to trial because he enjoys immunity as head of state&lt;/a&gt;.  And yet here we have one of the most senior members of the Catholic church dismissing repeated charges of the most disgusting violations of trust and abuse as "petty".&lt;br /&gt;&lt;br /&gt;Nothing quite reveals a man-made god as much as the dismissal of "petty" concerns.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-1184207859503968130?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/1184207859503968130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/04/institutional-abuse-is-not-gossip.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/1184207859503968130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/1184207859503968130'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/04/institutional-abuse-is-not-gossip.html' title='Institutional Abuse is not &amp;quot;Petty Gossip&amp;quot;'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-2855555033371689909</id><published>2010-04-03T13:28:00.000-07:00</published><updated>2010-04-04T10:34:54.218-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ps3'/><category scheme='http://www.blogger.com/atom/ns#' term='sony'/><title type='text'>PS3 System Update 3.21</title><content type='html'>Sony appear to be breaking new ground with the PS3: the only games console that &lt;em&gt;loses&lt;/em&gt; features with firmware 'upgrades'.  Yes, that's right: &lt;a href="http://uk.playstation.com/ps3/support/system-software/detail/item272598/Update-features-%28ver-3-21%29/"&gt;version 3.21&lt;/a&gt; drops support for the 'Install Other OS' feature.  This is almost on-par with the decision to drop software emulation of the Playstation 2, cutting off those large libraries of games that long-time users of Sony's console series have built up.&lt;br /&gt;&lt;br /&gt;The best part of it is being held hostage: you can't use the Playstation Network with anything but the latest firmware, so those who stubbornly refuse to upgrade will find themselves stuck with local-only access.&lt;br /&gt;&lt;br /&gt;Way to go, Sony!  Really making your customers feel valued here.&lt;br /&gt;&lt;br /&gt;Thankfully, George Hotz, who is &lt;a href="http://geohotps3.blogspot.com/2010/03/wait-you-are-removing-feature.html"&gt;similarly bemused&lt;/a&gt; has some advice: &lt;a href="http://geohotps3.blogspot.com/2010/03/dont-update.html"&gt;don't update&lt;/a&gt;.  He's already &lt;a href="http://news.bbc.co.uk/1/hi/technology/8478764.stm"&gt;hacked the PS3&lt;/a&gt;, and is looking to get a 3.21 firmware that doesn't lose the feature.&lt;br /&gt;&lt;br /&gt;The strange thing is, &lt;em&gt;he's&lt;/em&gt; the one that Sony will think is out of order.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-2855555033371689909?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/2855555033371689909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/04/ps3-system-update-321.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2855555033371689909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2855555033371689909'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/04/ps3-system-update-321.html' title='PS3 System Update 3.21'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-2737788966730259658</id><published>2010-02-10T02:05:00.000-08:00</published><updated>2010-02-10T02:20:25.103-08:00</updated><title type='text'>Determining the Function Name of a CODE Ref in Perl</title><content type='html'>One of the great things about Perl that it inherits from functional programming is the ability to treat functions as data.  You can create an function and assign it to a scalar reference.  You can take a reference to an existing, named function and do the same.  You're then free to pass that reference around, to be invoked later (the latter case is similar to function pointers in C, but the former is very different as the created sub can make use of variables defined in its lexical scope as it forms a &lt;a href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29"&gt;closure&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;While defining an API to a service I've been writing, I suddenly encountered the need to be able to differentiate between references to named functions and references to anonymous subroutines.  Quite simply, once I'd established a set of objects to operate on, a named routine should be invoked once for each, whereas an anonymous routine should be given the entire set to work with (this allowed a great deal of reuse within the existing codebase without limiting flexibility).&lt;br /&gt;&lt;br /&gt;While I suspected that Perl might be able to do this, it seemed like it would be some serious magic.  &lt;code&gt;Data::Dumper&lt;/code&gt; displays &lt;code&gt;sub { DUMMY }&lt;/code&gt; when printing &lt;code&gt;CODE&lt;/code&gt; references, so it's largely opaque.&lt;br /&gt;&lt;br /&gt;However, Perl comes with the &lt;a href="http://search.cpan.org/~dapm/perl-5.10.1/ext/B/B.pm"&gt;B&lt;/a&gt; module, providing access to Perl's internals as it's running.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;use B;&lt;br /&gt;&lt;br /&gt;sub named_routine {}&lt;br /&gt;&lt;br /&gt;my $named_ref = \&amp;named_routine;&lt;br /&gt;my $unnamed_ref = sub {};&lt;br /&gt;&lt;br /&gt;printf "%s\n", B::svref_2object($named_ref)-&gt;GV-&gt;NAME;&lt;br /&gt;printf "%s\n", B::svref_2object($unnamed_ref)-&gt;GV-&gt;NAME;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;this yields:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;named_routine&lt;br /&gt;__ANON__&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, provided that you're willing to avoid calling your subroutines __ANON__, you've got a good indication of what your &lt;code&gt;CODE&lt;/code&gt; reference actually points to.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-2737788966730259658?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/2737788966730259658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/02/determining-function-name-of-code-ref.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2737788966730259658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2737788966730259658'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/02/determining-function-name-of-code-ref.html' title='Determining the Function Name of a CODE Ref in Perl'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8805852557952721892</id><published>2010-01-08T07:06:00.000-08:00</published><updated>2010-01-08T07:14:05.725-08:00</updated><title type='text'>Centring Emacs on Screen</title><content type='html'>Something I've wanted to do for a while that's nevertheless eluded me is how to centre Emacs on-screen when it launches.  I'm a bit old fashioned and so like the default 80 character width, but I like as many rows as possible.&lt;br /&gt;&lt;br /&gt;At first, with functions like &lt;code&gt;(set-frame-height)&lt;/code&gt;, &lt;code&gt;(frame-pixel-height)&lt;/code&gt; and &lt;code&gt;(display-pixel-height)&lt;/code&gt;, it seems like it should be trivial, but the problem is that Emacs measures its frame height and width in &lt;em&gt;characters&lt;/em&gt;, whereas the pixel functions (obviously) work in pixels.&lt;br /&gt;&lt;br /&gt;The link comes in the from of &lt;code&gt;(frame-char-height)&lt;/code&gt; and &lt;code&gt;(frame-char-width)&lt;/code&gt;, which give the height and width of an idividual character in pixels.  Just evaluating the following expression should centre Emacs on your primary monitor:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(set-frame-height (selected-frame)&lt;br /&gt;    (floor (* 0.95 (/ (display-pixel-height)&lt;br /&gt;        (frame-char-height)))))&lt;br /&gt;(set-frame-position (selected-frame)&lt;br /&gt;      (floor (/ (- (display-pixel-width) (frame-pixel-width))&lt;br /&gt;         2))&lt;br /&gt;      (floor (* 0.02 (display-pixel-height))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you like this (maybe after some tweaking), you can just stuff the instructions in your &lt;code&gt;.emacs&lt;/code&gt; to get it every time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8805852557952721892?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8805852557952721892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/01/centring-emacs-on-screen.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8805852557952721892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8805852557952721892'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2010/01/centring-emacs-on-screen.html' title='Centring Emacs on Screen'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8330770237792909171</id><published>2009-12-23T05:21:00.001-08:00</published><updated>2009-12-23T06:10:40.118-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='politics labour education'/><title type='text'>Gutting Britain's Education System</title><content type='html'>I used to think that the Labour party was deliberately attacking the higher education system in the UK.  One of their first acts upon being elected into power in 1997 was to abolish the student grant, favouring loans instead and gifting graduates from low income families with £15-20K of debt before they'd even stepped into their professional career.  The thing that galled me about how that was announced at the time was when this was credited as an 'enabler' for students from low income families.  I &lt;em&gt;come&lt;/em&gt; from a low income family, and unless your degree course is conveyor-belt in/out, there's a very good chance that you could leave university with nothing but debt before your course is over.  By its final year, my course was less than a third of the size of the first.&lt;br /&gt;&lt;br /&gt;Now, 'Lord' Mandleson, our current Business Secretary, is &lt;a href="http://news.bbc.co.uk/1/hi/education/8427546.stm"&gt;slashing budgets for higher education&lt;/a&gt;, and at the same time asking universities to preserve standards of education.  I don't know how his brain works, but when the education system has been getting systematically destroyed by 'efficiency savings' for ten years, there simply isn't that much slack.  In addition, he'd like this to be accomplished in part by reducing three year degrees to two years 'as a way of easing the funding crisis'! Knocking a third off degree times will result in wonderfully incapable graduates, and weaken the value of the system as a whole.&lt;br /&gt;&lt;br /&gt;How about some honest &lt;em&gt;investment&lt;/em&gt;?  You know, where you put money into something and reap the rewards in the future?  Like when your graduates get higher paying jobs as a result of being better educated, and then pay higher taxes as a result?&lt;br /&gt;&lt;br /&gt;As I began, I used to think that the Labour government was attacking higher education.  Now I just think they're a mob of self-interested, incompetent fraudsters who've lost all touch with the real world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8330770237792909171?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8330770237792909171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/12/gutting-britains-education-system.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8330770237792909171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8330770237792909171'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/12/gutting-britains-education-system.html' title='Gutting Britain&apos;s Education System'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8589206663383667992</id><published>2009-12-21T01:42:00.000-08:00</published><updated>2009-12-22T01:07:38.615-08:00</updated><title type='text'>The Ultimate zsh Prompt</title><content type='html'>I cram a lot of information into my &lt;a href="http://zsh.org/"&gt;&lt;code&gt;zsh&lt;/code&gt;&lt;/a&gt; prompt.  I could describe it, but a picture covers it better:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_woBmp3G-OW8/SzCMS-oitrI/AAAAAAAAAE0/QsXgWQzMnwI/s1600-h/prompt.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 162px;" src="http://4.bp.blogspot.com/_woBmp3G-OW8/SzCMS-oitrI/AAAAAAAAAE0/QsXgWQzMnwI/s400/prompt.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5417984609405286066" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The code behind this, to be stuffed in your &lt;code&gt;$HOME/.zshrc&lt;/code&gt;, is:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: small;"&gt;&lt;br /&gt;autoload colors&lt;br /&gt;colors&lt;br /&gt;&lt;br /&gt;precmd()&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    PREV_RET_VAL=$?&lt;br /&gt;&lt;br /&gt;    if [ "$TERM" = "dumb" ]&lt;br /&gt;    then&lt;br /&gt;        PS1="%n@%m %% "&lt;br /&gt;        return&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    if [ $EUID -eq 0 ]&lt;br /&gt;    then&lt;br /&gt;        USER_COLOUR=red&lt;br /&gt;    else&lt;br /&gt;        USER_COLOUR=green&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    BASIC_COLOUR=cyan&lt;br /&gt;&lt;br /&gt;    # Basic prompt: 'user@host [history-number'"&lt;br /&gt;    PS1="%{${fg[$USER_COLOUR]}%}%n@%m %{${fg_bold[$BASIC_COLOUR]}%}%1~%{${fg[$BASIC_COLOUR]}%} [%!"&lt;br /&gt;&lt;br /&gt;    # Possibly append '/job-count', if the number of jobs is &gt; 0&lt;br /&gt;    if [ $#jobstates -ne 0 ]; then&lt;br /&gt;        PS1="${PS1}/%j"&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    # Possibly append '/error-status', if $? wasn't 0&lt;br /&gt;    if [ $PREV_RET_VAL -ne 0 ]&lt;br /&gt;    then&lt;br /&gt;        PS1="${PS1}/%{${fg_bold[red]}%}$PREV_RET_VAL%{${fg_bold[$BASIC_COLOUR]}%}"&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    # Close off the brackets for the status section, and finalise.&lt;br /&gt;    PS1="${PS1}] %% %{${fg_no_bold[default]}%}"&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This uses only shell built-ins, so is suitably fast for running at every prompt.&lt;br /&gt;&lt;br /&gt;One variant I used at work was to colour the prompt based on the &lt;code&gt;DEPLOYMENT_STATUS&lt;/code&gt; environment variables that the SAs set (one of 'prod', 'test', 'dev', 'cont'): red for production, purple for contingency, blue for test, and green for development, but that's not quite as useful at home. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8589206663383667992?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8589206663383667992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/12/ultimate-zsh-prompt.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8589206663383667992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8589206663383667992'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/12/ultimate-zsh-prompt.html' title='The Ultimate zsh Prompt'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_woBmp3G-OW8/SzCMS-oitrI/AAAAAAAAAE0/QsXgWQzMnwI/s72-c/prompt.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8986855952629805738</id><published>2009-12-06T02:15:00.001-08:00</published><updated>2009-12-06T02:16:06.841-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Readable Perl</title><content type='html'>Just finished reading &lt;a href="http://greenokapi.net/talks/ReadablePerl.pdf" title="Tips for readable Perl"&gt;this&lt;/a&gt;, and thought the examples and notes were excellent.&lt;br /&gt;&lt;br /&gt;I'm quite fond of writing readable Perl.  Hopefully my first &lt;a href="http://www.github.com"&gt;github&lt;/a&gt; hosted project, &lt;a href="http://github.com/dannywoodz/ctcs-2" title="CTCS2"&gt;CTCS2&lt;/a&gt;, backs that up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8986855952629805738?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8986855952629805738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/12/readable-perl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8986855952629805738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8986855952629805738'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/12/readable-perl.html' title='Readable Perl'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-6450177360305971106</id><published>2009-12-02T02:29:00.001-08:00</published><updated>2009-12-03T09:02:27.362-08:00</updated><title type='text'>Corporate Mistrust</title><content type='html'>On Monday, my wife called me to mention that she could buy a heavily discounted copy of Microsoft Office 2008 for Mac through a scheme at work.  The price was good enough to make it worthwhile, so I accepted her offer to buy me a copy.  Within a few minutes, she emailed me the download link and serial number.&lt;br /&gt;&lt;br /&gt;The installer asked for that serial number, which I carefully cut and pasted from the email.  Within a few minutes, the office icons are in the dock, and the updater was asking if I wanted to grab the latest patches.&lt;br /&gt;&lt;br /&gt;All good so far.&lt;br /&gt;&lt;br /&gt;Then I launch Word, and it asks again for my serial number.  Again, I copy and paste it into the dialog, expecting that, for whatever reason, I'll have to do this for Excel and PowerPoint, too.  Except that the serial number isn't accepted.  I try again.  Again, failure.  Exasperated, I opt for the clean uninstall option using the 'Remove Office' application installed as part of the suite.  It doesn't work: 'Remove Office' spends literally &lt;em&gt;hours&lt;/em&gt; searching for versions of office to remove, and when I eventually cancel, it tells me that it couldn't find any.  What, not even in the bog-standard '/Applications/Microsoft Office 2008' folder?  Why would it ever have looked there?&lt;br /&gt;&lt;br /&gt;So I manually uninstall it, removing all of the fragments that the damn procedure scattered throughout &lt;code&gt;~/Library&lt;/code&gt; and &lt;code&gt;/Library&lt;/code&gt;.  Reinstalling yields exactly the same procedure.&lt;br /&gt;&lt;br /&gt;The first contact with customer support yields a different download link, and them re-sending me the original key.  But the file from the alternate link is &lt;em&gt;identical&lt;/em&gt; to the original.  So, with the same key and the same file, what happens?  That's right: another key validation failure.&lt;br /&gt;&lt;br /&gt;So now it's back to customer support, this time providing them with a hardware signature, presumably so that they can generate a new key that's completely locked down to my laptop.&lt;br /&gt;&lt;br /&gt;This whole experience has left me wondering why I spent any money on the product at all.  The automatic assumption of "it's a copy!" has further damaged my already tarnished opinion of Microsoft as a company, and the textbook incompetence of their first-contact customer support is a frustrating waste of my time.&lt;br /&gt;&lt;br /&gt;Really, I wouldn't (and haven't) had this problem with &lt;a href="http://www.openoffice.org/"&gt;OpenOffice&lt;/a&gt;, which has the added bonus of being absolutely free.  The only reason I want Office is just so that I can open documents sent to me without losing content, and also to produce Word files that I know will open properly for those ridiculous agencies that accept it as their only CV format.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Edit: 3rd December, 2009&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Eventually, I got an obscenely long product activation code from Microsoft.  It didn't work.  The 'Remove Office' utility still doesn't work, so I'm left tossing shattered fragments of this sorry excuse for an office suite into the trash whenever I find them.  Definitely falls into the 'worse than useless' category.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-6450177360305971106?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/6450177360305971106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/12/corporate-mistrust.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/6450177360305971106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/6450177360305971106'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/12/corporate-mistrust.html' title='Corporate Mistrust'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8608981142018874793</id><published>2009-11-04T12:30:00.001-08:00</published><updated>2010-04-28T06:48:50.939-07:00</updated><title type='text'>orgtbl-mode</title><content type='html'>I've been using &lt;a href="http://www.orgmode.org" title="org-mode homepage"&gt;org-mode&lt;/a&gt; for some time for basic task planning, and occasionally for tracking time, but it always seems to have that bit more to learn.  One of the really cool features with &lt;code&gt;org-mode&lt;/code&gt; is its table editor: it makes it absolutely trivial to create and manipulate ASCII tables in plain text files (see &lt;a href="http://www.gnu.org/software/emacs/manual/html_node/org/Built_002din-table-editor.html"&gt;here&lt;/a&gt; for more).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://staff.science.uva.nl/~dominik/" title="Carsten Dominik's homepage"&gt;Carsten Dominik&lt;/a&gt;'s &lt;a href="http://www.youtube.com/watch?v=oJTwQvgfgMM" title="org-mode talk"&gt;org-mode presentation at Google&lt;/a&gt; intrigued me with the possibility of using that table editor in non-org files, but I lacked the inclination to investigate further until I stumbled across &lt;a href="http://www.youtube.com/watch?v=EQAd41VAXWo"&gt;this video&lt;/a&gt; showing the feature off by generating an HTML table from an &lt;code&gt;org-mode&lt;/code&gt; table source.&lt;br /&gt;&lt;br /&gt;If you're still interested, you should watch that now.  I'll do my best to explain how it's done when you're finished.&lt;br /&gt;&lt;br /&gt;....&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Creating an HTML table with &lt;code&gt;orgtbl-mode&lt;/code&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Quite simply, &lt;code&gt;orgtbl-mode&lt;/code&gt; is an Emacs &lt;em&gt;minor mode&lt;/em&gt; that embeds into whichever major mode you happen to be working in.  Within the context of an &lt;code&gt;org-mode&lt;/code&gt; table within that document, &lt;code&gt;org-mode&lt;/code&gt; table commands apply.  Elsewhere in the document, your major mode (&lt;code&gt;java-mode&lt;/code&gt;, &lt;code&gt;cperl-mode&lt;/code&gt;, etc.) is in charge.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Insertion Point for the HTML Table&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;You specify where the org table is going to appear with a pair of markers.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#BEGIN RECEIVE ORGTBL books&lt;br /&gt;#END RECEIVE ORGTBL books&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;The first character there ('#') should be whichever comment character makes sense for your major mode&lt;/em&gt;.  So you'll use '//' for Java, C and C++, '%' for LaTeX, &lt;code&gt;&amp;lt;!-- ... --&amp;gt;&lt;/code&gt; for HTML and XML, etc.  The reason for this simple: you don't want these markers polluting the textual sources that you're composing in whichever major mode you're in.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The &lt;code&gt;orgtbl&lt;/code&gt; Source Table&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Next, you'll define (somewhere in the document) a section for you to specify the org table.  It helps here if your language has a block-comment structure (like the above HTML style comment, or &lt;code&gt;/* ... */&lt;/code&gt; for C, or the &lt;code&gt;comment&lt;/code&gt; package for LaTeX).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt;#+ORGTBL: SEND books orgtbl-to-html&lt;br /&gt;| Title               | Cost  |&lt;br /&gt;|---------------------+-------|&lt;br /&gt;| Programming Clojure | 30.00 |&lt;br /&gt;| Programming Perl    | 25.00 |&lt;br /&gt;|---------------------+-------|&lt;br /&gt;| TOTAL               |       |&lt;br /&gt;--&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(The reason I advise about block comments is that I was seeing problems generating the table unless &lt;code&gt;#+ORGTBL:&lt;/code&gt; was a the beginning of the line).&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;#+ORGTBL&lt;/code&gt; line includes the &lt;code&gt;SEND&lt;/code&gt; command (the counterpart to the &lt;code&gt;RECEIVE&lt;/code&gt; in the previous markup); the table name (to match up with the appropriate &lt;code&gt;RECEIVE&lt;/code&gt;: there could be many); and the translation function that takes the &lt;code&gt;org-mode&lt;/code&gt; table and produces the HTML, LaTeX, or whatever output.&lt;br /&gt;&lt;br /&gt;Once you've got the table above, with the cursor in the field where you want the table to go, type &lt;code&gt;C-u C-c =&lt;/code&gt;.  At this point, focus will be transferred to the minibuffer, which will look like this:&lt;br /&gt;&lt;br /&gt;&lt;code style="display:block"&gt;&lt;br /&gt;Field formula B4=&lt;span style="background-color='red'"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Here, you can enter spreadsheet-like formulae.  I'm still learning here, but a good answer to the prompt is:&lt;br /&gt;&lt;br /&gt;&lt;code style="display:block"&gt;&lt;br /&gt;vsum(@I..@II)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;...which will neatly place a total for the Cost field in that slot (and also place a formula definition under the table), so that it looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt;#+ORGTBL: SEND books orgtbl-to-html&lt;br /&gt;| Book                |  Cost |&lt;br /&gt;|---------------------+-------|&lt;br /&gt;| Programming Clojure | 20.00 |&lt;br /&gt;| Programming Perl    | 25.00 |&lt;br /&gt;|---------------------+-------|&lt;br /&gt;| TOTAL               |   45. |&lt;br /&gt;#+TBLFM: @4$2=vsum(@I..@II)&lt;br /&gt;--&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;@4$2&lt;/code&gt; is the specifier for the cell where the total is to appear (row 4, column 2).  Formulae are automatically updated as you move columns around, insert new ones, add new rows, etc., but when you're done editing, hit &lt;code&gt;C-c C-c&lt;/code&gt; on the formula line to update the table values.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Generating the HTML Table&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;On the &lt;code&gt;#+ORGTBL:&lt;/code&gt; line, hit &lt;code&gt;C-c C-c&lt;/code&gt;, and the HTML for your table will automatically be generated from the &lt;code&gt;orgtbl&lt;/code&gt; source and be inserted between the &lt;code&gt;BEGIN RECEIVE&lt;/code&gt; and &lt;code&gt;END RECEIVE&lt;/code&gt; markers.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Updating the HTML Table&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;When you want to change your HTML table, just change the &lt;code&gt;org-mode&lt;/code&gt; table, update the formula with &lt;code&gt;C-c C-c&lt;/code&gt; on the formula line, and then regenerate with the same keystrokes on the &lt;code&gt;SEND&lt;/code&gt; line, and your HTML table will be refreshed with the new state.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8608981142018874793?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8608981142018874793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/11/orgtbl-mode.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8608981142018874793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8608981142018874793'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/11/orgtbl-mode.html' title='orgtbl-mode'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-7468398387427298029</id><published>2009-10-18T09:49:00.000-07:00</published><updated>2009-10-18T09:51:48.460-07:00</updated><title type='text'>Goodbye lad.</title><content type='html'>It's been less than five months since I &lt;a href="http://dynamic-thinking.blogspot.com/2009/05/goodbye-old-man.html"&gt;buried Garfield&lt;/a&gt; under his favourite tree at my mother's.  Today, I gave him company, and set &lt;a href="http://dynamic-thinking.blogspot.com/2009/10/another-sad-day.html"&gt;Jake's&lt;/a&gt; ashes down next to his.&lt;br /&gt;&lt;br /&gt;Take care of the pup for me, old man.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-7468398387427298029?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/7468398387427298029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/goodbye-lad.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7468398387427298029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7468398387427298029'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/goodbye-lad.html' title='Goodbye lad.'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-4537159473939990648</id><published>2009-10-14T08:06:00.001-07:00</published><updated>2009-10-14T13:22:04.949-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mormons religion gay rights'/><title type='text'>The Religious Persecution Complex</title><content type='html'>In the best traditions of throwing a tantrum to get their way, the Mormons (I keep typing 'morons') in California are upset because &lt;a href="http://www.google.com/hostednews/ap/article/ALeqM5iCrSWSM6V3N-yi3tAJOBlnjwR27wD9BAEL1O0"&gt;public support for their suppression of gay rights is waning&lt;/a&gt;.  Enshrining the rights of those who think differently in law is a threat to their religious freedom, they whine.  Furthermore, they have the audacity to portray themselves as the persecuted minority, "similar to the intimidation of Southern blacks during the civil rights movement".&lt;br /&gt;&lt;br /&gt;Every time I try to think of an appropriately outraged response, my brain just shuts down.  It simply can't deal with that level of stupidity.&lt;br /&gt;&lt;br /&gt;Religions that kick and scream whenever they don't get their way are a common sight: the Catholics are upset because they were &lt;a href="http://www.youtube.com/watch?v=3bObItmxAGc&amp;amp;feature=player_embedded"&gt;mocked&lt;/a&gt; by US comedienne, Sarah Silverman, who suggested that selling the Vatican and giving the proceeds to the poor would feed the hungry of the world.  The Muslims get upset every time someone doesn't automatically yield to their demands for respect (seriously, why would a non-Muslim care about the traditions and taboos of Islam?)  And then the Mormons, bat-shit crazy even by the high-bar set by standard Christianity, think that California legislation threatening to overturn their hate campaign is an attack on their religion.&lt;br /&gt;&lt;br /&gt;I'm an atheist.  I really don't care which gods or spirits or entities you worship.  But when it infringes upon the rights of other people who wish to live their lives &lt;em&gt;free&lt;/em&gt; of religiously-inspired bigotry, I start to have a problem.  And this notion that every disagreement is an attack against your god or gods, or your freedom to practice religion: forget it.  I don't have a problem with imaginary entities.  But I do have a problem with stupidity, and if you think that your particular brand of stupidity is allowed because it's sanctioned by an invisible being, that doesn't give it any more weight.&lt;br /&gt;&lt;br /&gt;In a close to this rant, you might be thinking of some suitably boring tirade that involves either quotes from whichever book you believe is the One, True, Unaltered Word of God, or threats of violence or hellfire.  Save your fingers.  If I am wrong, and there really is a god, I'll happily answer to him/her/it when it's all over: the supreme creator of the universe doesn't need your assistance in eliminating me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-4537159473939990648?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/4537159473939990648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/religious-persecution-complex.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4537159473939990648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4537159473939990648'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/religious-persecution-complex.html' title='The Religious Persecution Complex'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-7440124138473059900</id><published>2009-10-13T13:15:00.001-07:00</published><updated>2009-10-13T13:46:41.875-07:00</updated><title type='text'>Keyboard and Mouse Unresponsive in GDM</title><content type='html'>A fairly major upgrade of Xorg at the weekend left my &lt;a href="http://www.gentoo.org/"&gt;Gentoo Linux&lt;/a&gt; box in a state where mouse and keyboard input no longer worked at the GDM login screen.  &lt;br /&gt;&lt;br /&gt;Nasty.&lt;br /&gt;&lt;br /&gt;First port of call was &lt;code&gt;/var/log/Xorg.0.log&lt;/code&gt;, in which I could see some suspicious lines:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: small"&gt;&lt;br /&gt;(II) LoadModule: "mouse"&lt;br /&gt;(II) Loading /usr/lib/xorg/modules/input//mouse_drv.so&lt;br /&gt;(II) Module mouse: vendor="X.Org Foundation"&lt;br /&gt;        compiled for 1.5.3, module version = 1.4.0&lt;br /&gt;        Module class: X.Org XInput Driver&lt;br /&gt;        ABI class: X.Org XInput driver, version 2.1&lt;br /&gt;(EE) module ABI major version (2) doesn't match the server's version (4)&lt;br /&gt;(II) UnloadModule: "mouse"&lt;br /&gt;(II) Unloading /usr/lib/xorg/modules/input//mouse_drv.so&lt;br /&gt;(EE) Failed to load module "mouse" (module requirement mismatch, 0)&lt;br /&gt;(EE) No input driver matching `mouse'&lt;br /&gt;(II) LoadModule: "kbd"&lt;br /&gt;(II) Loading /usr/lib/xorg/modules/input//kbd_drv.so&lt;br /&gt;(II) Module kbd: vendor="X.Org Foundation"&lt;br /&gt;        compiled for 1.5.3, module version = 1.3.2&lt;br /&gt;        Module class: X.Org XInput Driver&lt;br /&gt;        ABI class: X.Org XInput driver, version 2.1&lt;br /&gt;(EE) module ABI major version (2) doesn't match the server's version (4)&lt;br /&gt;(II) UnloadModule: "kbd"&lt;br /&gt;(II) Unloading /usr/lib/xorg/modules/input//kbd_drv.so&lt;br /&gt;(EE) Failed to load module "kbd" (module requirement mismatch, 0)&lt;br /&gt;(EE) No input driver matching `kbd'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, a version mismatch between driver modules and the updated X server.&lt;br /&gt;&lt;br /&gt;The solution?&lt;br /&gt;&lt;br /&gt;&lt;code&gt;emerge -1 x11-drivers/xf86-input-{evdev,keyboard,mouse}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Followed by:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;/etc/init.d/xdm restart&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The downside?  &lt;em&gt;The keyboard wasn't working&lt;/em&gt;.  So I had to issue these commands from my Macbook Pro after &lt;code&gt;ssh&lt;/code&gt;ing into my Linux box.&lt;br /&gt;&lt;br /&gt;If you're stuck without &lt;code&gt;ssh&lt;/code&gt; access, hold down &lt;code&gt;Alt-SysRq&lt;/code&gt; and then press &lt;code&gt;r&lt;/code&gt; and then &lt;code&gt;e&lt;/code&gt; to kill the X server, then &lt;code&gt;Alt-Shift-F1&lt;/code&gt; to get back to a virtual terminal, and then log in as root.  Not pretty, but I'd guess that it'd work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-7440124138473059900?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/7440124138473059900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/keyboard-and-mouse-unresponsive-in-gdm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7440124138473059900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7440124138473059900'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/keyboard-and-mouse-unresponsive-in-gdm.html' title='Keyboard and Mouse Unresponsive in GDM'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-3979919210393102878</id><published>2009-10-12T05:30:00.000-07:00</published><updated>2009-10-12T06:14:43.201-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books ebooks sony amazon drm'/><title type='text'>Avoiding e-Readers</title><content type='html'>There has been a great deal of hype about electronic books from &lt;a href="http://www.sony.co.uk/hub/reader-ebook"&gt;Sony&lt;/a&gt; and &lt;a href="http://www.amazon.com/gp/product/B0015T963C/ref=amb_link_84995353_1?ie=UTF8&amp;%3Brw_absolute=y&amp;pf_rd_m=A3P5ROKL5A1OLE&amp;pf_rd_s=auto-sparkle&amp;pf_rd_r=1ZJB93D5CF51TQ6S631D&amp;pf_rd_t=301&amp;pf_rd_p=472912793&amp;pf_rd_i=kindle"&gt;Amazon&lt;/a&gt; but, as much as I like shiny new gadgets, I just can't get excited over these offerings.  Fundamentally, I like replacements for old ideas to be better than their predecessors in every measurable way, but e-readers are more give-and-take.&lt;br /&gt;&lt;br /&gt;On the plus side, you've almost eliminated the weight/bulk factor.  You can buy books on-the-go, and have them almost instantly available for reading.  The Kindle offers free Wikipedia access, which is handy for settling those pub debates.  The text-to-speech feature could occasionally be useful if you just want to stare out of the train window for a while on the way to work rather than squinting tired eyes at text on a page.&lt;br /&gt;&lt;br /&gt;But then, the negatives are huge:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;Sure, the battery life is impressive, but it's still a battery life that dead-tree just doesn't have to worry about.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;It's no big deal if you lose a book or drop it in the pool by mistake on holiday, but doing the same with these pricey devices is a blow, both from the perspective that it cost so damn much and that your &lt;em&gt;entire&lt;/em&gt; holiday reading was on it.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Digital Rights Management.  This is wrong on so many levels it's hard to know where to start.  Want to lend a book to your friend?  Not allowed.  Want to view it on a broader range of devices than the publisher of your book wants?  Not allowed.  Have you inadvertently bought something that shouldn't have been sold to you?  No problem (for the publishers) -- your reseller can &lt;a href="http://arstechnica.com/tech-policy/news/2009/07/amazon-sold-pirated-books-raided-some-kindles.ars?utm_source=microblogging&amp;utm_medium=arstch&amp;utm_term=Main%20Account&amp;utm_campaign=microblogging"&gt;remotely remove the book from your library&lt;/a&gt; (the fact that this was done with George Orwell's 1984 is deliciously ironic).&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;On a DRM-related note, you can only buy books for your reader from online stores affiliated with the manufacturer of your device, and it's not too difficult to envision a music industry-like scenario where a given title is only available on a given platform.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;(and this is the part that makes me think I'm getting old...) it just doesn't &lt;em&gt;feel&lt;/em&gt; good.  Some throw-away books I don't really care about, but others, I want to feel the paper under my fingers to get a feel for it (I have a copy of the Smalltalk &lt;a href="http://www.amazon.com/Smalltalk-80-Language-Implementation-Adele-Goldberg/dp/0201113716"&gt;'Blue Book'&lt;/a&gt;, printed in 1983, that exudes that fuzzy feeling)&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Maybe that's it.  The only books I'd be happy to have on an electronic reader would be ones that I don't care about; ones that are effectively disposable.  But disposable and expensive don't sit well together.&lt;br /&gt;&lt;br /&gt;How can e-readers get it right?  They have to be better than 'old-style' books, and that involves both a significant drop in price and the ditching of the DRM millstone.  Some unique opportunities arise in the case of corrections and updated versions, as well.  Does your technical book have a new, updated edition?  Maybe you could get it cheaper because you owned the previous one.  Maybe you can wirelessly submit feedback or corrections back to the author/publisher.  When you're part way through a series, waiting for the author to publish the next volume, wouldn't it be useful say, "I'm interested in this series" and automatically be notified when it's available?&lt;br /&gt;&lt;br /&gt;Despite my dislike of the current state of affairs, there's lots of potential for the platform, but only if some draconian notions of control relax their grip on its throat.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-3979919210393102878?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/3979919210393102878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/avoiding-e-readers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/3979919210393102878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/3979919210393102878'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/avoiding-e-readers.html' title='Avoiding e-Readers'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-859701596749396779</id><published>2009-10-10T00:52:00.001-07:00</published><updated>2009-10-10T00:52:28.364-07:00</updated><title type='text'>Thank you, US Airways!</title><content type='html'>I spent some work-time in southern California about a month ago, involving a long day of travel from Glasgow to Philadelphia, and then from there to San Diego.  With my entertainment loaded onto my iPod Touch, I was prepared.&lt;br /&gt;&lt;br /&gt;At least, until I left it on the plane in Philadelphia on the way to the states.&lt;br /&gt;&lt;br /&gt;Having realised almost immediately that I'd left it, I asked a US Airways representative if they could help out but, without a procedure to follow, there was nothing that could be done to get my iPod from the plane.  It was mildly frustrating, but when it came down to it, it was my fault for leaving it!  Still, I left my details in the hopes that it might turn up later.&lt;br /&gt;&lt;br /&gt;Back home two weeks later, I got a call from US Airways asking if I had lost something, and when I confirmed the what and the when was told that they could take my postal address to return it to me.  It took a while to get it across the Atlantic, but it finally arrived yesterday.&lt;br /&gt;&lt;br /&gt;So thank you US Airways!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-859701596749396779?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/859701596749396779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/thank-you-us-airways.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/859701596749396779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/859701596749396779'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/thank-you-us-airways.html' title='Thank you, US Airways!'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-2026901758241107155</id><published>2009-10-07T02:06:00.001-07:00</published><updated>2009-10-07T02:32:37.442-07:00</updated><title type='text'>Regular Expressions in Erlang</title><content type='html'>My favourite general-purpose language is still &lt;a href="http://www.perl.com"&gt;Perl&lt;/a&gt;.  It's not that it's the &lt;em&gt;best&lt;/em&gt; at everything, but that it's &lt;em&gt;good enough&lt;/em&gt; for just about anything (and better than most).&lt;br /&gt;&lt;br /&gt;Probably as a side-effect of what many would consider this misguided affection, one of the first things I look at in a new language is its &lt;a href="http://www.regular-expressions.info/"&gt;regular expression&lt;/a&gt; support.  Mostly, this is a no-brainer: Perl 5 is the de-facto standard, and &lt;a href="http://www.pcre.org"&gt;its regex engine&lt;/a&gt; is available as a library to link into your favourite C-binding language.&lt;br /&gt;&lt;br /&gt;So I was disappointed initially when looking for advice on regular expressions in &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt;.  The first hit on Google (at the time of this writing) is &lt;a href="http://schemecookbook.org/Erlang/RegexChapter"&gt;here&lt;/a&gt;, and indicates the &lt;code&gt;regex&lt;/code&gt; module.  Unfortunately, that module is really, really limited compared to the mind-bending flexibility of the Perl 5 engine.&lt;br /&gt;&lt;br /&gt;I was disappointed.  I'm going to re-write my &lt;a href="http://www.rahul.net/dholmes/ctorrent/ctcs.html"&gt;CTCS&lt;/a&gt; &lt;a href="http://github.com/dannywoodz/ctcs-2"&gt;clone&lt;/a&gt; in Erlang, and it makes quite a lot of use of regular expressions to extract information from the various messages &lt;code&gt;ctorrent&lt;/code&gt; sends throughout its lifetime.  In this case, it was a bit of a show-stopper: there's absolutely no point in doing the re-write if it's going to be more difficult to create the new version than improve the old.&lt;br /&gt;&lt;br /&gt;But then, salvation!  The &lt;a href="http://www.erlang.org/doc/man/re.html"&gt;re&lt;/a&gt; module, an (almost) mapping onto PCRE!&lt;br /&gt;&lt;br /&gt;Suddenly, extracting groups from a string was easy:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;regex_example() -&gt;&lt;br /&gt;  Name = "Danny Woods",&lt;br /&gt;  { match, [ Forename, Surname ] } =&lt;br /&gt;     re:run(Name, "(\\w+)\\s+(\\w+)", [{capture,all_but_first,list}]),&lt;br /&gt;  { Forename, Surname }.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The escaped backslashes are ugly, but the direct capturing of groups as a list is pretty sweet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-2026901758241107155?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/2026901758241107155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/regular-expressions-in-erlang.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2026901758241107155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2026901758241107155'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/regular-expressions-in-erlang.html' title='Regular Expressions in Erlang'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-4550561646288924569</id><published>2009-10-05T12:39:00.001-07:00</published><updated>2009-10-05T12:45:34.435-07:00</updated><title type='text'>Another Sad Day</title><content type='html'>It's been almost six months since &lt;a href="http://dynamic-thinking.blogspot.com/2009/05/sad-day.html"&gt;Garfield died&lt;/a&gt;.  Every Garfield needs his Odie, and my Garfield's was Jake.  We had to take Jake to his final visit to the vet's today: he was diagnosed with aggressive terminal cancer three weeks ago and given six months to live, but a turn for the worse last week pulled that date back to today.  He was sixteen.&lt;br /&gt;&lt;br /&gt;We got Jake as a pup in 1993, and he kept those puppy looks right up until the end.  I visited him at my mother's yesterday, and gave him a hug and touched our foreheads together like we've done since we were both young.  He was the best of dogs.&lt;br /&gt;&lt;br /&gt;Sleep peacefully boy.&lt;br /&gt;&lt;br /&gt;I will miss you.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align:center;"&gt;&lt;img src="http://lh6.ggpht.com/_woBmp3G-OW8/SspLWLiHuaI/AAAAAAAAADs/NmIchrdZhzA/jake.jpg?imgmax=800" alt="jake.jpg" border="0" width="800" height="600" /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-4550561646288924569?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/4550561646288924569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/another-sad-day.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4550561646288924569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/4550561646288924569'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/10/another-sad-day.html' title='Another Sad Day'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_woBmp3G-OW8/SspLWLiHuaI/AAAAAAAAADs/NmIchrdZhzA/s72-c/jake.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-2152926387250723846</id><published>2009-09-09T06:58:00.000-07:00</published><updated>2009-09-09T07:03:04.946-07:00</updated><title type='text'>Wastage</title><content type='html'>I stumbled across &lt;a href="http://www.youtube.com/watch?v=8KswnjMa-MQ"&gt;this amusing video&lt;/a&gt; of a cat drinking by dunking its head under a flowing tap.  Even this light-hearted fun had some people in the comments bemoaning the wasted water of a tap being on for a few minutes of recorded video.&lt;br /&gt;&lt;br /&gt;Then, with the subject of wasted water fresh in my mind, I switched tabs to &lt;a href="http://www.progressivepuppy.com/the_progressive_puppy/2009/09/school-outing-ends-in-peer-pressure-baptisms.html"&gt;this story&lt;/a&gt; (also from Reddit), and almost snorted my tea.&lt;br /&gt;&lt;br /&gt;It was funny at the time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-2152926387250723846?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/2152926387250723846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/09/wastage.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2152926387250723846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/2152926387250723846'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/09/wastage.html' title='Wastage'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-6927381162828970204</id><published>2009-09-07T13:54:00.001-07:00</published><updated>2009-09-07T14:03:37.253-07:00</updated><title type='text'>Building MPlayer from SVN on Mac OS X Snow Leopard</title><content type='html'>I use the command line &lt;code&gt;mplayer&lt;/code&gt; on Mac OS.  The only competition for this superb video player is &lt;a href="http://www.videolan.org/vlc/"&gt;VLC&lt;/a&gt;, but sometimes I like to just quickly launch something without a bulky UI getting in the way.&lt;br /&gt;&lt;br /&gt;But today I upgraded to &lt;a href="http://www.apple.com/macosx/"&gt;Snow Leopard&lt;/a&gt;, distinctive from it's predecessor in being a truly native 64-bit operating system.  And my SVN checkout of &lt;a href="http://www.mplayerhq.hu/design7/dload.html"&gt;MPlayer&lt;/a&gt; stopped working, giving me a green video window and needing some effort to kill.  So, to get MPlayer working, you're going to need the following:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://developer.apple.com/Mac/"&gt;Apple Developer Tools&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.libpng.org/pub/png/libpng.html"&gt;libpng&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.ijg.org/"&gt;libjpeg&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://sourceforge.net/projects/freetype/"&gt;freetype&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;...and, of course, your MPlayer sources.  If you want FAAC support, get &lt;a href="http://www.audiocoding.com/downloads.html"&gt;libfaac&lt;/a&gt; and build/install it using the same procedure as for &lt;code&gt;freetype&lt;/code&gt; below.&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #f5f5f5; padding: 1em;"&gt;&lt;br /&gt;&lt;dl&gt;&lt;br /&gt;  &lt;dt&gt;Install the Apple Developer Tools using the graphical installer.&lt;/dt&gt;&lt;br /&gt;  &lt;dt&gt;Build &lt;code&gt;libpng&lt;/code&gt; and &lt;code&gt;libjpeg&lt;/code&gt;:&lt;/dt&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;./configure --arch=x86_64&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;make&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;sudo make install&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;  &lt;dt&gt;Build &lt;code&gt;freetype&lt;/code&gt;:&lt;/dt&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;./configure --target=x86_64-Darwin&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;make&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;sudo make install&lt;/code&gt;&lt;/dd&gt; &lt;br /&gt;  &lt;dt&gt;Build &lt;code&gt;mplayer&lt;/code&gt;:&lt;/dt&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;./configure --target=x86_64-Darwin --enable-menu&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;make&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;    &lt;dd&gt;&lt;code&gt;sudo make install&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;&lt;/dl&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now, you should have a native 64-bit &lt;code&gt;/usr/local/bin/mplayer&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #f5f5f5; padding: 1em;"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="color:green;"&gt;danny@mirror&lt;/span&gt;&lt;span style="color:cyan;"&gt;  ~ [1] % &lt;/span&gt;file /usr/local/bin/mplayer&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;/usr/local/bin/mplayer: Mach-O 64-bit executable x86_64&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="color:green;"&gt;danny@mirror&lt;/span&gt;&lt;span style="color:cyan;"&gt; ~ [2] %&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Success!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-6927381162828970204?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/6927381162828970204/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/09/building-mplayer-from-svn-on-mac-os-x.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/6927381162828970204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/6927381162828970204'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/09/building-mplayer-from-svn-on-mac-os-x.html' title='Building MPlayer from SVN on Mac OS X Snow Leopard'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-5325738165212761539</id><published>2009-08-27T14:31:00.001-07:00</published><updated>2009-08-27T14:31:19.352-07:00</updated><title type='text'>Why I Write My CV in LaTeX</title><content type='html'>For many people, even technical people, LaTeX is a relic.  I recently had a chat with some colleagues who were looking to write documentation in a format that could be easily converted into other formats (PDF, HTML, etc.), which could maintain its own indexing and cross-referencing easily, and which would, of course, look good.  I mentioned LaTeX and got some amused eye-rolling and comments about how no-one uses that anymore.&lt;br /&gt;&lt;br /&gt;Even if that &lt;em&gt;were&lt;/em&gt; true, I maintain my CV in LaTeX.  Why?  Simple:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;It enables absolute control over what gets rendered, and where, on the page.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;There's &lt;a href="http://miktex.org"&gt;MiKTeX&lt;/a&gt; for Windows, &lt;a href="http://www.uoregon.edu/~koch/texshop/"&gt;TeXShop&lt;/a&gt; for Mac and &lt;a href="http://www.tug.org/texlive/"&gt;TeX Live&lt;/a&gt; for Linux.  In other words, it's available for your favourite platform.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;The source files are plain text.  This makes for easy versioning using your &lt;a href="http://git-scm.com/"&gt;favourite&lt;/a&gt; &lt;a href="http://bazaar-vcs.org/"&gt;version&lt;/a&gt; &lt;a href="http://subversion.tigris.org/"&gt;control&lt;/a&gt; &lt;a href="http://www.nongnu.org/cvs/"&gt;system&lt;/a&gt;, and thereafter, comparing the differences between any two versions.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Producing good looking PDFs is simple with &lt;code&gt;pdflatex&lt;/code&gt;.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Sure, it takes more time than knocking something together in Microsoft Word or OpenOffice Writer, but there's a distinct satisfaction to be enjoyed from tweaking and crafting something until it's exactly how you want it to be.&lt;br /&gt;&lt;br /&gt;Definitely not for everyone, but if you've gone to all the trouble to develop a skill-set that you're proud of, you may as well take the effort to show it off in the best way possible!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-5325738165212761539?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/5325738165212761539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/08/why-i-write-my-cv-in-latex.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5325738165212761539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5325738165212761539'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/08/why-i-write-my-cv-in-latex.html' title='Why I Write My CV in LaTeX'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-621671145026654050</id><published>2009-08-10T01:35:00.001-07:00</published><updated>2009-08-10T01:35:07.679-07:00</updated><title type='text'>ScotRail is Stuck in the 80's</title><content type='html'>My wife and I went on a shopping trip to Edinburgh yesterday, involving a train journey to Glasgow Central station, a short walk to Queen Street station, and another train ride to Edinburgh.&lt;br /&gt;&lt;br /&gt;Now, for some truly bizarre reason, it's cheaper to get a return ticket to Central, and then a separate return ticket for the Glasgow&amp;ndash;Edinburgh link, than it is to get a return from East Kilbride to Edinburgh.  Go figure.  But we skip over that little bit of insanity, and ask for &lt;em&gt;one&lt;/em&gt; return ticket from East Kilbride to Glasgow Central, and &lt;em&gt;two&lt;/em&gt; returns from Glasgow to Edinburgh.  See, I work in Glasgow, so already have a season ticket.  With a queue building up, we pay, bundle our tickets together and get on the train.&lt;br /&gt;&lt;br /&gt;As it starts to pull away, we look through the tickets to see that the ticket office in East Kilbride has issued us with &lt;em&gt;two&lt;/em&gt; return tickets for the East Kilbride to Glasgow link.  Mildly irritating, but no big issue: we can just get a refund on the tickets that we're not going to use.  We ask the conductor on the train, and get the response that he can't issue a refund, because he'd be out of pocket.  We'd need to get the station at East Kilbride to do that, or possibly get it done at the ticket office at Central.  He's a ScotRail ticket conductor, and these are ScotRail tickets, and he can't...  Something in my head implodes from the stupidity.  I thank him for his 'help' and he goes away.&lt;br /&gt;&lt;br /&gt;Once in Central Station, we're told that we can't get the refund there: we'd have to get it from East Kilbride.  The reasoning is that they didn't issue the physical tickets, so the ticket number wouldn't be on their system, only in the East Kilbride one.  The most he can do is give us a form to fill out.&lt;br /&gt;&lt;br /&gt;Now, this is our outbound journey.  It's 13:00, and our home station closes at 17:00.  Chances of making it back from Edinburgh in time?  Approximately zero.&lt;br /&gt;&lt;br /&gt;Both stations at East Kilbride and Glasgow Central are run by ScotRail.  The conductor on the train is a ScotRail employee.  It's a mere &lt;em&gt;ten miles&lt;/em&gt; between the town and the city, and this is 2009.  And ScotRail still don't have the facilities to provide refunds, except at the issuing station?&lt;br /&gt;&lt;br /&gt;Embarrassing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-621671145026654050?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/621671145026654050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/08/scotrail-is-stuck-in-80.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/621671145026654050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/621671145026654050'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/08/scotrail-is-stuck-in-80.html' title='ScotRail is Stuck in the 80&amp;#39;s'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-9086952101859675577</id><published>2009-06-21T07:48:00.001-07:00</published><updated>2009-06-21T07:48:51.921-07:00</updated><title type='text'>Other Uses for the FreeBSD Daemon?</title><content type='html'>A friend of mine has been visiting from the Czech Republic over the weekend, an infrequent thing that inevitably results in visits to East Kilbride's pubs and nightclubs that we'll later regret.  Some special strangeness last night came in the form of a sex-toy vending machine in the male toilets in Shenanigans in East Kilbride's town centre.  Who would have thought that the FreeBSD daemon (right) was moonlighting as a purveyor of kinky goods?&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh4.ggpht.com/_woBmp3G-OW8/Sj5Hzv3T8NI/AAAAAAAAADM/In3mLbDcs6I/vendie.png?imgmax=800" alt="vendie.png" border="0" width="185" height="247" float="right" /&gt;&lt;img src="http://lh4.ggpht.com/_woBmp3G-OW8/Sj5H3zTiFLI/AAAAAAAAADQ/YwyDa-7ifdY/bsd.jpg?imgmax=800" alt="bsd.jpg" border="0" width="175" height="185" float="right" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-9086952101859675577?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/9086952101859675577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/06/other-uses-for-freebsd-daemon.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/9086952101859675577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/9086952101859675577'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/06/other-uses-for-freebsd-daemon.html' title='Other Uses for the FreeBSD Daemon?'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_woBmp3G-OW8/Sj5Hzv3T8NI/AAAAAAAAADM/In3mLbDcs6I/s72-c/vendie.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-290783152706043061</id><published>2009-06-20T05:15:00.001-07:00</published><updated>2009-06-20T05:20:59.885-07:00</updated><title type='text'>A Minimal Java Applet in Clojure</title><content type='html'>Clojure's ahead-of-time compilation features allow it to operate seamlessly with Java classes, but one quirk that I noticed when writing a Java applet was that the security environment in applets tends not to be too happy with reflective method calls.  Overriding an applet's &lt;code&gt;paint&lt;/code&gt; method like this is therefore a no-go:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defn -paint [instance g]&lt;br /&gt;  (.drawString g "Hello from Clojure!" 50 50))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The problem here is that the &lt;code&gt;.drawString&lt;/code&gt; method is reflectively invoked against the given &lt;code&gt;Graphics&lt;/code&gt; object.&lt;br /&gt;&lt;br /&gt;This can be overcome with type-hints, letting the compiler know what the given 'g' is so that it can generate the code for a direct call, keeping the applet security manager happy.&lt;br /&gt;&lt;br /&gt;A minimal applet might therefore look something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(ns djw&lt;br /&gt;  (:import (java.awt Graphics2D))&lt;br /&gt;  (:gen-class&lt;br /&gt;   :name DJW&lt;br /&gt;   :extends java.applet.Applet))&lt;br /&gt;(defn -paint [instance #^Graphics2D g]&lt;br /&gt;  (.drawString g "Hello from Clojure!" 50 50))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note the type-hint, &lt;code&gt;#^Graphics2D&lt;/code&gt; in the signature of the &lt;code&gt;paint&lt;/code&gt; function.&lt;br /&gt;&lt;br /&gt;If you're interested, the associated HTML file to run this in &lt;code&gt;appletviewer&lt;/code&gt; or in a browser looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;object classid="java:DJW.class" type="application/x-java-applet" archive="applet.jar,clojure.jar" width="200" height="100" codebase="."&amp;gt;&lt;br /&gt;&amp;lt;/object&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice that &lt;code&gt;clojure.jar&lt;/code&gt; is in the &lt;code&gt;archive&lt;/code&gt; field of the &lt;code&gt;object&lt;/code&gt; tag, along with &lt;code&gt;applet.jar&lt;/code&gt; (containing the precompiled &lt;code&gt;class&lt;/code&gt; files for the Clojure applet).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-290783152706043061?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/290783152706043061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/06/minimal-java-applet-in-clojure.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/290783152706043061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/290783152706043061'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/06/minimal-java-applet-in-clojure.html' title='A Minimal Java Applet in Clojure'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-3623933716939170993</id><published>2009-06-16T11:54:00.001-07:00</published><updated>2009-06-19T01:27:09.251-07:00</updated><title type='text'>UK to get 'World Class' Broadband?</title><content type='html'>I had to laugh at &lt;a href="http://news.bbc.co.uk/1/hi/technology/8102756.stm" title="BBC News"&gt;this&lt;/a&gt; article on the BBC: a new 50p tax on fixed lines in the UK to enable 'digital Britain' providing, among other things (&lt;span style="font-size: smaller; color: #bbb;"&gt;up to&lt;/span&gt;) 50Mbps by 2017.  A special highlight from our wonderfully inept Prime Minister:&lt;br /&gt;&lt;br /&gt;&lt;cite&gt;&lt;br /&gt;"Britain is going to lead the world. This is us taking the next step into the future to being the digital capital of the world. -- Gordon Brown&lt;br /&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;Step back a bit... &lt;em&gt;having 50Mbps broadband by &lt;strong&gt;2017&lt;/strong&gt; is going to make us the 'the digital capital of the world'&lt;/em&gt;?  Is he aware that South Korea is &lt;a href="http://gigaom.com/2009/02/01/by-2012-koreans-will-get-a-gigabit-per-second-broadband-connection/" title="South Korea's target broadband speed"&gt;aiming for 1Gbps&lt;/a&gt; by &lt;strong&gt;&lt;em&gt;2012&lt;/em&gt;&lt;/strong&gt;?!? (in case you're wondering, that's 20 times faster, five years earlier).  Japan has 100Mbps &lt;em&gt;&lt;a href="http://www.websiteoptimization.com/bw/0711/" title="Survey of Advertised National Broabdband Speeds"&gt;now&lt;/a&gt;&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;I sometimes wonder exactly which planet Gordon Brown is living on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-3623933716939170993?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/3623933716939170993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/06/uk-to-get-class-broadband.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/3623933716939170993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/3623933716939170993'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/06/uk-to-get-class-broadband.html' title='UK to get &amp;#39;World Class&amp;#39; Broadband?'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-7071847943606145203</id><published>2009-06-08T13:35:00.001-07:00</published><updated>2009-06-09T03:45:45.991-07:00</updated><title type='text'>Clojure: First Steps into Compilation and Class Generation</title><content type='html'>I've never quite understood class generation in Clojure.  The &lt;a href="http://clojure.org/compilation" title="Clojure pre-compilation documentation"&gt;documentation&lt;/a&gt; is a little terse, and working examples seem to be hard to come by.  So here's my walkthrough.&lt;br /&gt;&lt;br /&gt;First, I'm assuming that we'll be creating Clojure objects from Java, calling methods on those Clojure objects from bog-standard Java code.  This, I think, is the most likely scenario for the budding Clojure hacker who wants to write part of an existing Java system in Clojure.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Environment&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;First, you'll need to have obtained your &lt;code&gt;clojure.jar&lt;/code&gt;, either from the snapshots &lt;a href="http://code.google.com/p/clojure/downloads/list"&gt;here&lt;/a&gt;, or &lt;a href="http://code.google.com/p/clojure/source/checkout"&gt;from the Subversion repository&lt;/a&gt; and building yourself.&lt;br /&gt;&lt;br /&gt;Next, in whatever environment you're using, add the full path to &lt;code&gt;clojure.jar&lt;/code&gt; to your &lt;code&gt;CLASSPATH&lt;/code&gt;.  Also add "&lt;code&gt;.&lt;/code&gt;" and "&lt;code&gt;classes&lt;/code&gt;" (both &lt;em&gt;relative&lt;/em&gt; paths, not absolute).  You'll see why later.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Clojure Code&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;In the directory you're building from,  create the directory structure for your package, Java-style.  I'm going to be putting my Clojure code in &lt;code&gt;org/djw/sample.clj&lt;/code&gt;, so &lt;code&gt;org/djw&lt;/code&gt; will have to exist beforehand.&lt;br /&gt;&lt;br /&gt;In &lt;code&gt;sample.clj&lt;/code&gt;, most of the magic's in the namespace declaration.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(ns org.djw.sample                      ;; 1&lt;br /&gt;  (:import (javax.swing JFrame))        ;; 2&lt;br /&gt;  (:gen-class                           ;; 3&lt;br /&gt;   :name org.djw.DJW                    ;; 4&lt;br /&gt;   :extends javax.swing.JFrame          ;; 5&lt;br /&gt;   :constructors {[String] [String]}    ;; 6&lt;br /&gt;   :init initialise                     ;; 7&lt;br /&gt;   :implements [Runnable]               ;; 8&lt;br /&gt;   :state fiddlyBits))                  ;; 9&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;1. This is your Clojure namespace.  It doesn't mean much from Java-land.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;2. You can import any classes used by your Clojure file here.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;3. &lt;code&gt;:gen-class&lt;/code&gt; allows the compiler to generate Java bytecode files.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;4. This is the fully-qualified name of the Java class you want to emit.  The Clojure &lt;code&gt;compile&lt;/code&gt; directive generates quite a few class files that your Java code doesn't need to know about: the one in &lt;code&gt;:name&lt;/code&gt; is an exception: it's what your Java code will &lt;code&gt;import&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;5. If your class subclasses something other than &lt;code&gt;Object&lt;/code&gt;, name it here, as normal&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;6. I want to have a &lt;code&gt;String&lt;/code&gt; constructor that calls the &lt;code&gt;String&lt;/code&gt; constructor in &lt;code&gt;JFrame&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;7. The initialiser function for new instances.  I lack imagination, so have called it &lt;code&gt;initialise&lt;/code&gt; here.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;8. Horribly, my new class is both a GUI element (a &lt;code&gt;JFrame&lt;/code&gt;) and a &lt;code&gt;Runnable&lt;/code&gt;.  Since you can implement many interfaces, this appears in a literal vector.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;9. The &lt;code&gt;initialise&lt;/code&gt; function gets to attach some Clojure-side state to the object being created (you'll see that in a bit).  The &lt;code&gt;:state&lt;/code&gt; specifier creates a final instance method  to access that state from Java.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;This leaves two functions to implement in the Clojure code: &lt;code&gt;initialise&lt;/code&gt; and &lt;code&gt;run&lt;/code&gt; (the latter required by &lt;code&gt;Runnable&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defn -initialise [message]&lt;br /&gt;  [[message] (ref {:message message})])&lt;br /&gt;&lt;br /&gt;(defn -run [instance]&lt;br /&gt;  (let [message (:message @(.fiddlyBits instance))]&lt;br /&gt;    (println message)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note the dash in front of the function names (this is the default &lt;code&gt;:prefix&lt;/code&gt; from &lt;code&gt;:gen-class&lt;/code&gt;).  Also, note that the function specified by &lt;code&gt;:init&lt;/code&gt; in &lt;code&gt;:gen-class&lt;/code&gt; &lt;em&gt;didn't&lt;/em&gt; get an instance to play with, whereas &lt;code&gt;run&lt;/code&gt; (an instance method), does.  This instance is the object that the method was invoked against, effectively &lt;code&gt;this&lt;/code&gt; from Java.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;initialise&lt;/code&gt; has to return a vector of two elements: the first consists of the arguments to pass to the superclass constructor.  The second is the state that should be attached on a per-instance basis.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;run&lt;/code&gt; is a &lt;code&gt;Runnable.run&lt;/code&gt; implementation, and just prints out the message that the instance was created with.  Note that the state is accessed with &lt;code&gt;(.fiddlyBits instance)&lt;/code&gt;, returning the &lt;code&gt;ref&lt;/code&gt;-wrapped Clojure map, dereferenced with '@' as normal and with the &lt;code&gt;:message&lt;/code&gt; key used to look up the associated value.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Compiling the Clojure Code to &lt;code&gt;.class&lt;/code&gt; Files&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Create a directory called &lt;code&gt;classes/[package-name]&lt;/code&gt;, in my case &lt;code&gt;classes/org/djw&lt;/code&gt;.  Why &lt;code&gt;classes&lt;/code&gt;?  Well, that's what Clojure's global &lt;code&gt;*compile-path*&lt;/code&gt; variable is by default, so is the root where the &lt;code&gt;compile&lt;/code&gt; command emits &lt;code&gt;.class&lt;/code&gt; files.  &lt;em&gt;That's why you added it to your &lt;code&gt;CLASSPATH&lt;/code&gt; above&lt;/em&gt; (you did do that, didn't you..?)&lt;br /&gt;&lt;br /&gt;Since &lt;code&gt;clojure.jar&lt;/code&gt; is on your &lt;code&gt;CLASSPATH&lt;/code&gt;, you can start a Clojure REPL with just '&lt;code&gt;java clojure.main&lt;/code&gt;'.  You can now compile the &lt;code&gt;./org/djw/sample.clj&lt;/code&gt; like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;danny@mirror Desktop [10] % java clojure.main&lt;br /&gt;Clojure 1.1.0-alpha-SNAPSHOT&lt;br /&gt;user=&gt; (compile 'org.djw.sample)&lt;br /&gt;org.djw.sample&lt;br /&gt;user=&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And that's it.  &lt;code&gt;classes/org/djw&lt;/code&gt; will now contain &lt;code&gt;org.djw.DJW&lt;/code&gt; (as per &lt;code&gt;gen-class&lt;/code&gt;'s &lt;code&gt;:name&lt;/code&gt; field).  It'll also contain a bunch of other &lt;code&gt;.class&lt;/code&gt; files: don't delete these, they are required!  Clojure creates a &lt;code&gt;.class&lt;/code&gt; file per function (including unnamed functions), as well as another for initialisation.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Java Code&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;This has been a lot of effort so far.  But the good news that this allows Java to talk to Clojure-generated class files without having any idea that Clojure was the source language.  The Java code in &lt;code&gt;Test.java&lt;/code&gt; to use it might look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import org.djw.DJW;&lt;br /&gt;&lt;br /&gt;public class Test&lt;br /&gt;{&lt;br /&gt;  public static void main(String [] args)&lt;br /&gt;  {&lt;br /&gt;    DJW djw = new DJW("Hello");&lt;br /&gt;    new Thread(djw).start();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And that's it.  &lt;code&gt;DJW&lt;/code&gt; is the class name, and a new instance is obtained just as with any other class.  It faithfully implements &lt;code&gt;Runnable&lt;/code&gt;, as specified in the Clojure code, and it can be duly run from a &lt;code&gt;Thread&lt;/code&gt; created from Java.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Compiling and Running the Java Code&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The Java can be compiled just as with any other.  Remember that the &lt;code&gt;classes&lt;/code&gt; folder must be in your &lt;code&gt;CLASSPATH&lt;/code&gt; for &lt;code&gt;javac&lt;/code&gt; to see the definition of &lt;code&gt;DJW&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;With &lt;code&gt;clojure.jar&lt;/code&gt;, &lt;code&gt;'.'&lt;/code&gt; and &lt;code&gt;classes&lt;/code&gt; in your &lt;code&gt;CLASSPATH&lt;/code&gt;, you can just run as you'd expect:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;danny@mirror Desktop [30] % javac Test.java&lt;br /&gt;danny@mirror Desktop [31] % java Test      &lt;br /&gt;Hello&lt;br /&gt;danny@mirror Desktop [32] %&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By now, you've defined a class definition in Clojure, prompted instance creation from Java, initialised the object in Clojure, handed it to a thread in Java, and printed out a message in Clojure.  That's a fair amount of bouncing around, especially for such a trivial example, but hopefully you've found it useful for what you need.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-7071847943606145203?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/7071847943606145203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/06/clojure-first-steps-into-compilation.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7071847943606145203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7071847943606145203'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/06/clojure-first-steps-into-compilation.html' title='Clojure: First Steps into Compilation and Class Generation'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-7960906868563060945</id><published>2009-05-24T14:36:00.001-07:00</published><updated>2009-05-24T14:36:10.439-07:00</updated><title type='text'>Goodbye, Old Man</title><content type='html'>I buried Garfield's ashes today, under his favourite tree (claw marks included) at my mother's house.  He went in the best way possible, but I've shed more than a few tears since &lt;a href="http://dynamic-thinking.blogspot.com/2009/05/sad-day.html"&gt;his death&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;He did well.&lt;br /&gt;&lt;br /&gt;Rest in peace, old man.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-7960906868563060945?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/7960906868563060945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/05/goodbye-old-man.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7960906868563060945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7960906868563060945'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/05/goodbye-old-man.html' title='Goodbye, Old Man'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-6096882393661257045</id><published>2009-05-24T06:58:00.001-07:00</published><updated>2009-05-26T02:31:26.233-07:00</updated><title type='text'>Clojure on FreeBSD 7</title><content type='html'>Getting a native Java on FreeBSD 7 is not straightforward.  It involves going through the instructions at &lt;a href="http://www.freebsd.org/java/" title="FreeBSD Java homepage"&gt;freebsd.org/java&lt;/a&gt; and manually fetching packages that have generally since been superseded by point-versions (which you can't use or the ports system won't install them).  Once they're all in &lt;code&gt;/usr/ports/distfiles&lt;/code&gt;, a &lt;code&gt;make install&lt;/code&gt; in &lt;code&gt;/usr/ports/java/jdk16&lt;/code&gt; will, several hours of hard compilation later, enable you to checkout a fresh copy of &lt;a href="http://www.clojure.org/" title="Clojure home page"&gt;Clojure&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Finally, success:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_woBmp3G-OW8/ShlTywhyzJI/AAAAAAAAACs/E3jthm5-LYQ/s1600-h/clojure-freebsd.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 86px;" src="http://1.bp.blogspot.com/_woBmp3G-OW8/ShlTywhyzJI/AAAAAAAAACs/E3jthm5-LYQ/s400/clojure-freebsd.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5339390964709641362" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-6096882393661257045?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/6096882393661257045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/05/clojure-on-freebsd-7.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/6096882393661257045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/6096882393661257045'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/05/clojure-on-freebsd-7.html' title='Clojure on FreeBSD 7'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_woBmp3G-OW8/ShlTywhyzJI/AAAAAAAAACs/E3jthm5-LYQ/s72-c/clojure-freebsd.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-5184041613532081190</id><published>2009-05-22T02:47:00.001-07:00</published><updated>2009-05-22T02:58:11.959-07:00</updated><title type='text'>Switching between Header and Implementation Files with Emacs</title><content type='html'>I often find myself working with C or C++ code that follows the pattern of parallel source/include directories, probably with lots of layers in between (e.g. &lt;code&gt;project/include/some-controller/some-aspect/something.h&lt;/code&gt; and &lt;code&gt;project/src/some-controller/some-aspect/something.cpp&lt;/code&gt;).  Quickly switching between both saves on keystrokes and sanity, so I wrote this little chunk of elisp, bound to &lt;code&gt;ctrl-alt-g&lt;/code&gt; (for no particular reason other than the combination is easy to mash):&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: smaller;"&gt;&lt;br /&gt;(defun djw-c-toggle-impl-header-view (create-if-nonexistent)&lt;br /&gt;  (interactive "P")&lt;br /&gt;  (let* ((mode (if (string-equal (file-name-extension (buffer-file-name))&lt;br /&gt;     "h")&lt;br /&gt;     :switch-to-implementation :switch-to-header))&lt;br /&gt;  (toggle-tags (list (cons "/Include/" "/Src/")&lt;br /&gt;       (cons "/include/" "/src/")))&lt;br /&gt;  (from-fn (if (eq mode :switch-to-implementation)&lt;br /&gt;        #'car #'cdr))&lt;br /&gt;  (to-fn (if (eq mode :switch-to-implementation)&lt;br /&gt;      #'cdr #'car))&lt;br /&gt;  (source-file-name (buffer-file-name))&lt;br /&gt;  (case-fold-search nil)) ;; I want case-sensitive matching throughout this block.&lt;br /&gt;    (dolist (pair toggle-tags)&lt;br /&gt;      (setf source-file-name (replace-regexp-in-string (funcall from-fn pair)&lt;br /&gt;             (funcall to-fn pair)&lt;br /&gt;             source-file-name)))&lt;br /&gt;    (setf source-file-name&lt;br /&gt;   (replace-regexp-in-string&lt;br /&gt;    (if (eq mode :switch-to-implementation)&lt;br /&gt;        "h\$" "cpp\$")&lt;br /&gt;    (if (eq mode :switch-to-implementation)&lt;br /&gt;        "cpp" "h")&lt;br /&gt;    source-file-name))&lt;br /&gt;    (message (format "Looking for %s" source-file-name))&lt;br /&gt;    (if (or (file-exists-p source-file-name)&lt;br /&gt;     create-if-nonexistent)&lt;br /&gt; (find-file source-file-name)&lt;br /&gt; (message (format "Can't find '%s'" source-file-name)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If the counterpart file is missing, it won't be created unless the function is invoked with a prefix argument (&lt;code&gt;C-u C-M-g&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;There's probably some extension to CC mode or the like that already does something like this, but in the absence of reading the manual, this works well for me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-5184041613532081190?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/5184041613532081190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/05/switching-between-header-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5184041613532081190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5184041613532081190'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/05/switching-between-header-and.html' title='Switching between Header and Implementation Files with Emacs'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-1188412861735741882</id><published>2009-05-13T00:40:00.001-07:00</published><updated>2009-05-13T09:17:08.551-07:00</updated><title type='text'>Sad Day</title><content type='html'>My cat died today.&lt;br /&gt;&lt;br /&gt;His name was Garfield, and he was 19.  I got him as a kitten when I was 13.  I came downstairs this morning to find him on his favourite cushion on the couch; it was the only time that he didn't raise his head to meow/croak back at me.&lt;br /&gt;&lt;br /&gt;He had a good life. His last day was spent sunning himself in the back garden; his last meal was his favourite roast chicken; and last night, when I was working at my computer, he came up for a cuddle and a purr.&lt;br /&gt;&lt;br /&gt;As the vet said to me a few months ago, "You don't last that long without good bits".  Garfield was made with the best.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align:center;"&gt;&lt;img src="http://lh6.ggpht.com/_woBmp3G-OW8/Sgrye4uMZII/AAAAAAAAACc/FUG1_rh4J3M/garfield.jpg?imgmax=800" alt="garfield.jpg" border="0" width="400" height="400" /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Goodbye, old man.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-1188412861735741882?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/1188412861735741882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/05/sad-day.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/1188412861735741882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/1188412861735741882'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/05/sad-day.html' title='Sad Day'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_woBmp3G-OW8/Sgrye4uMZII/AAAAAAAAACc/FUG1_rh4J3M/s72-c/garfield.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-7105185163855219708</id><published>2009-04-28T06:06:00.001-07:00</published><updated>2009-05-02T02:35:33.837-07:00</updated><title type='text'>Setting Colours with JavaScript</title><content type='html'>Something I thought would be easy turns out to have lots of different answers, none of which are particularly convenient: how do you compute a colour value in JavaScript, and then update some element on the page to use that colour?&lt;br /&gt;&lt;br /&gt;Most solutions I've seen involve some kind of hard-coded hexadecimal conversion table, which is more than a little clunky.  So here's another approach.  Here, the value used to compute the colours is a ratio, with a value from 0.0 and up (normally in the 0.0 to 2.0 region, but theoretically unbounded at the top).  I want to use &lt;span style="color:red;"&gt;red&lt;/span&gt; to indicate a ratio of 0.0, &lt;span style="color:green;"&gt;green&lt;/span&gt; for ratios of 2.0 or more, and a smooth range of colours in between.&lt;br /&gt;&lt;br /&gt;So, onto th JavaScript (yes, I have the ratio conveniently in a hash table):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var ratio = parseFloat(data["ratio"]);&lt;br /&gt;var red   = 255 - (ratio * 255);  // calculate&lt;br /&gt;var green = ratio * 128;&lt;br /&gt;if (red &lt; 0) red = 0;             // clamp&lt;br /&gt;if (green &gt; 255) green = 255;&lt;br /&gt;var colour = ((red &lt;&lt; 16) | (green &lt;&lt; 8) | 0).toString(16);&lt;br /&gt;while (colour.length &lt; 6) colour = '0' + colour;&lt;br /&gt;document.getElementById("ratio").style.color = '#' + colour;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The magic is in knowing that colours are typically represented as a red-green-blue triplet, with a byte in each channel (range 0-255).  Blue doesn't feature in our range, so it's always zero.  So, assembling the necessary triplet is just a matter of getting the clamped value for the right fields, and then OR-ing them together in a bitwise fashion after putting the red and green values in the correct place with the appropriate shifting.  Then the &lt;code&gt;toString(16)&lt;/code&gt; returns that integer in base-16, which happens to be what makes sense in CSS land.  Finally, pad the string out with zeroes on the left (the string needs to be six characters long, then slap on the '#' to have it make sense in CSS land and you're done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-7105185163855219708?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/7105185163855219708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/04/setting-colours-with-javascript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7105185163855219708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7105185163855219708'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/04/setting-colours-with-javascript.html' title='Setting Colours with JavaScript'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-5618523938695941254</id><published>2009-02-15T10:38:00.001-08:00</published><updated>2009-02-15T10:38:57.866-08:00</updated><title type='text'>Java Brain Damage</title><content type='html'>I don't generally buy into bashing Java, a trend all-too-fashionable among dynamic language programmers (and even C++ programmers, for some reason).  But I just stumbled across something when writing &lt;a href="http://clojure.org" title="Clojure homepage"&gt;Clojure&lt;/a&gt; that annoyed me: with a &lt;code&gt;JFrame&lt;/code&gt;, &lt;code&gt;getLayout&lt;/code&gt; doesn't return the object set by a previous &lt;code&gt;setLayout(aLayout)&lt;/code&gt; call.  Why?  Because the layout actually gets set on the &lt;code&gt;JFrame&lt;/code&gt;'s content pane, and that's not what &lt;code&gt;getLayout&lt;/code&gt; is looking at.&lt;br /&gt;&lt;br /&gt;Now, I remember the days where &lt;code&gt;JFrame.add&lt;/code&gt; triggered a runtime exception: "Don't use &lt;code&gt;add&lt;/code&gt;!  Use &lt;code&gt;getContentPane().add()&lt;/code&gt; instead!" or something like that.  Somewhere down the line, someone appears to have had the great idea of changing that so that &lt;cod&gt;add&lt;/code&gt; made sense on a &lt;code&gt;JFrame&lt;/code&gt; by deferring to the content pane, but symmetry has been broken in the process.  Nice!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-5618523938695941254?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/5618523938695941254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/02/java-brain-damage.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5618523938695941254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/5618523938695941254'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/02/java-brain-damage.html' title='Java Brain Damage'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-7142697830127982065</id><published>2009-02-08T04:27:00.001-08:00</published><updated>2009-02-08T05:13:40.891-08:00</updated><title type='text'>Smalltalk: Why it's NOT Good</title><content type='html'>There's been a fair buzz in the Smalltalk blogs (&lt;a href="http://methodsandmessages.vox.com/library/post/comparing-smalltalk-and-java.html?_c=feed-atom"&gt;here&lt;/a&gt; and &lt;a href="http://www.cincomsmalltalk.com/blog/blogView?showComments=true&amp;printTitle=Smalltalk_-_When_you_have_hard_problems...&amp;entry=3411454104"&gt;here&lt;/a&gt;) about generally positive Smalltalk-applicability &lt;a href="http://stackoverflow.com/questions/515061/where-do-you-use-smalltalk"&gt;comments made on StackOverflow&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now, I like to think of myself as a generalist, and a bit of a language geek.  In my various jobs I've written a great deal of Smalltalk (VisualWorks), Java, C++, C and Perl, but have also spent a fair amount of fun time working with Squeak, SBCL Common Lisp, Clojure and Erlang.  I'm a huge fan of Linux and Unix, and believe that the shell is a vastly under-used resource.&lt;br /&gt;&lt;br /&gt;This is where I personally find Smalltalk to be annoying.&lt;br /&gt;&lt;br /&gt;Don't get me wrong: it's an amazing language and development environment.  With something like Eclipse, you write some arcane text files and--after running them through a compiler that you didn't really need the IDE for anyway--you have your application.  With Smalltalk, the IDE &lt;em&gt;is&lt;/em&gt; the application: you just iteratively refine it until it becomes what you want to ship.  Awesome stuff.&lt;br /&gt;&lt;br /&gt;But that same self-contained structure is what hurts it.  When I write C, I tend to use &lt;a href="http://www.gnu.org/software/emacs/" title="Emacs text editor"&gt;Emacs&lt;/a&gt;, enhanced with a &lt;a href="http://zagadka.vm.bytemark.co.uk/magit/" title="Emacs git integration"&gt;bunch&lt;/a&gt; &lt;a href="http://ecb.sourceforge.net/" title="Emacs code browser"&gt;of&lt;/a&gt; &lt;a href="http://code.google.com/p/yasnippet/" title="snippets for Emacs"&gt;add-ons&lt;/a&gt;.  I use the &lt;a href="http://git-scm.com/" title="The git source control system"&gt;git&lt;/a&gt; source control system.  I use &lt;code&gt;diff&lt;/code&gt; and &lt;code&gt;patch&lt;/code&gt; to throw experimental code snippets at colleagues, and they do the same with me.&lt;br /&gt;&lt;br /&gt;However, my choices don't stop them from using Eclipse, and the master source repository being &lt;a href="http://subversion.tigris.org/" title="The Subversion source control system"&gt;Subversion&lt;/a&gt;.  Furthermore, when I need to write Java or Perl, I can use the vast majority of the tool stack that I've accumulated just by switching buffers in Emacs.  Simply put, I get to transfer most of my skills between tools.&lt;br /&gt;&lt;br /&gt;In Smalltalk, it's all-or-nothing.  Shell tools are useless on the image.  You can't edit code in your favourite editor (well, you can, but unless you're using &lt;a href="http://smalltalk.gnu.org/"&gt;GNU Smalltalk&lt;/a&gt;, it's inconvenient to the point of being unusable).  On top of that, you need a special, integrated source control system that's most likely dictated by your vendor, with migration being difficult-to-impossible.&lt;br /&gt;&lt;br /&gt;For me, this single-mindedness it what stops Smalltalk being my favourite language (well, that and a single-threaded virtual machine and non-native GUI widgets).  For now, &lt;a href="http://www.perl.com/" title="Homepage for the Perl programming language"&gt;Perl&lt;/a&gt; retains that crown (despite it being fashionable to bash it these days), with &lt;a href="http://clojure.org/" title="Clojure homepage"&gt;Clojure&lt;/a&gt; looking very, very interesting as a possible successor...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-7142697830127982065?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/7142697830127982065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/02/smalltalk-why-it-not-good.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7142697830127982065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/7142697830127982065'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/02/smalltalk-why-it-not-good.html' title='Smalltalk: Why it&amp;#39;s NOT Good'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7718565330748264667.post-8240675886479733411</id><published>2009-01-03T04:40:00.001-08:00</published><updated>2009-01-03T04:40:26.002-08:00</updated><title type='text'> Factorials with Clojure and SBCL</title><content type='html'>I've been playing with &lt;a href="http://clojure.org/" title="Clojure Homepage"&gt;Clojure&lt;/a&gt; for a few days now, and have to admit being really impressed.  It's &lt;em&gt;almost&lt;/em&gt; as flexible as Lisp, and has simple and complete access to the &lt;em&gt;massive&lt;/em&gt; Java class libraries.  It's also fully dynamic, unlike the largely static Java language that it shares a platform with.&lt;br /&gt;&lt;br /&gt;One of the somewhat contrived examples used to show off dynamic languages is calculations of factorials: this quickly differentiates languages that are more considerate to the machine than the programmer, as the explosive growth of values produced by the function quickly overflows the register-bound &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;long&lt;/code&gt; types in C and Java.&lt;br /&gt;&lt;br /&gt;So I tried this out in Clojure, and hacked out this in a few minutes:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defn factorial [x]&lt;br /&gt;  (loop [current x&lt;br /&gt;	 accum   1]&lt;br /&gt;    (if (= current 1)&lt;br /&gt;      accum&lt;br /&gt;      (recur (- current 1)&lt;br /&gt;	     (* current accum)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;loop/recur&lt;/code&gt; offers optimisation similar to tail call optimisation, allowing you to avoid blowing the stack with large numbers.  Trying this out with 100,000, my dual core Macbook Pro chugged away for just over four minutes to produce a number almost half a million digits long.&lt;br /&gt;&lt;br /&gt;I was impressed.&lt;br /&gt;&lt;br /&gt;Curious about how a more traditional Lisp would cope, I tried this largely equivalent code out in &lt;a href="http://www.sbcl.org/" title="SBCL Homepage"&gt;SBCL&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defun factorial (x)&lt;br /&gt;  (labels ((helper (current accum)&lt;br /&gt;	     (if (= current 1)&lt;br /&gt;		 accum&lt;br /&gt;		 (helper (1- current)&lt;br /&gt;			 (* current accum)))))&lt;br /&gt;    (helper x 1)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;which, on the same machine, performed the same calculation in under 13 &lt;em&gt;seconds&lt;/em&gt;.  WOW.&lt;br /&gt;&lt;br /&gt;The purely iterative version:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defun factorial (x)&lt;br /&gt;  (do ((current x (1- current))&lt;br /&gt;       (accum 1 (* current accum)))&lt;br /&gt;      ((= current 1)&lt;br /&gt;       accum)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;performed almost identically.&lt;br /&gt;&lt;br /&gt;Pretty awesome. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7718565330748264667-8240675886479733411?l=dynamic-thinking.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dynamic-thinking.blogspot.com/feeds/8240675886479733411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/01/ive-been-playing-with-clojure-for-few.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8240675886479733411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7718565330748264667/posts/default/8240675886479733411'/><link rel='alternate' type='text/html' href='http://dynamic-thinking.blogspot.com/2009/01/ive-been-playing-with-clojure-for-few.html' title=' Factorials with Clojure and SBCL'/><author><name>Danny</name><uri>http://www.blogger.com/profile/15763567497153080240</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='http://bp1.blogger.com/_woBmp3G-OW8/R4J7-dNsNXI/AAAAAAAAAAM/BM8utJGL19s/S220/polarbear.gif'/></author><thr:total>3</thr:total></entry></feed>
