Musings
muse: to turn something over in the mind meditatively and often inconclusively
Open road, open visor

Today was a scorcher. Matt and I belted out to Franschoek for breakfast this morning. We didn't quite make breakfast and had to settle for lunch instead.

I had to lift Matt from his place down to his offices to fetch his bike this morning. Even though this was only the second time I'd taken a passenger Matt trustingly jumped onto the back sans helmet and off we went. Sans helmet because Matt's gear was also at the office.

It wasn't as difficult as I'd expected. Stopping and maneuvering at low speeds is a bit tricky (Matt's offices are on one of the higher floors so we took the spiral ramp up to that level). You have to remember the additional weight when you come to a stop and drop onto one leg. But when we were moving I hardly noticed the weight difference at all.

The ride itself was great. We took the N2 out to Stellenbosch and then headed over to Franschoek via Helshoogte. The road's a bit bumpy but the scenery is unrivalled. Next time I'm taking the camera with. Not much beats a hot Summer day, an open visor and a roaring engine. After lunch we screamed back along the N1. It struck me this afternoon how odd it is that biking is so much better when there's more than one of you, and yet regardless of the group on the road you're still essentially on your own. No wonder so many people in IT bike: it's a group activity with almost zero social interaction (or at least it can be).

I really need a decent map of the region. All the maps I've got are either of Cape Town proper or cover such a large area (the whole country for example) so as to make them useless for local navigation. There are plenty of back roads worth exploring around here.

Posted at 03:01 PM

Plants and things that resemble them

garden_before_small.jpg We've just come through a few weeks of juggling keys, workmen, trucks, and (the cherry on top) the smell of manure permeating the house.

Our new garden is in and we're quite pleased with the results. First off I have to give all the credit to Claire. It was her idea. She's the one who did all of the legwork. She pulled together the various people she needed to go from conception to inception to what you see here, to the right.

The new garden should be a little hardier (and water wise). As far as possible, the selection of plants incorporates species indigenous to the region. A few of the original "tennants" remain behind because they're established and established is (apparently) valuable. We've done away with the lawn out back. It was small, uneven and required mowing. In its stead we now have some pavers with a minty groundcover planted between them. Eventually this should grow out and insted of using deodorant I'll have the option of rolling around on the pavers and going to work smelling like an after dinner mint.

garden_intermed_small.jpg A large part of the work involved tearing up concrete down the side of the house. There was a tremendous amount of space just going to waste. We've put up a wooden wall with a gate, giving us access to the back that doesn't involve going through the house (handy if you're carrying manure for example). We've paved a small part of it to use as utility space (for storing things like our outside bin and corpses that need to be disposed of), and so we have the option of parking the bike out of sight (although it's sloped so if the bike needs to be push started I'm in deep kak). We've also put in a fair sized water feature and now have the soothing sound of water trickling outside of the lounge window. Soothing, that is, until your bladder starts playing up.

garden_after_small.jpg We've put up trellises down the side. One trellis screens the back garden from the side path (providing an air of mystery: "What do you think's down here Doris?") and another screens the whole lot from the aforementioned utility area. A paved path winds its way down the side of the house, past the water feature and out to the front of the house.

Some of the new plants include a plethora of clivias (yes, they have their own website; I'm as surprised as you are). We have an established specimen at the back that's looking quite spectacular at the moment and we've redistributed a large collection of younger clivias around the new planting areas. We've planted a young indigenous tree and a lot of Wild Jasmine, a creeper that will eventually grow up the walls and trellises, and that resembles (oddly enough) Jasmine, both visually and fragrantly.

I have to be honest, I was skeptical initially, especially when we were looking over the quotes we'd been given. But I think it was worth it and I'm glad we took the plunge.

Posted at 06:33 PM

A spate of weird dreams

The last week has seen any number of bizarre dreams including, but by no means limited to:

  • Looking after my pet fish, but forgetting to top their water up. By the time I remembered they'd almost run dry and I feared they were dead. But they were survivors and pulled through with only one side-effect: they'd turned into labradors (sleepy ones at that).
  • A female friend (a female friend with a distinct aversion to the idea of kids) falling pregnant. Then she's not pregnant. Then she's pregnant again and marrying my brother. This would have been slightly less odd if it hadn't all transpired within the space of a single weekend.
  • The most recent involved chasing a generic Hannibal Lecter character through Cape Town in an ambulance driven by a (rather good looking) blonde filled to the brim with kids. Hannibal (we'll call him that for want of a name) escaped from the house of a colleague who'd locked him in a cage to study him (this sounds more and more like a bad movie plot). We drove round and round the city but I woke up before we had any success.

It's a real laugh riot in there.

Posted at 08:35 PM

1.5 kinda grows on you

I'm waaay behind on my blog at the moment. I have an inbox full of notes (I drop myself a quick email every time something comes up I might want to blog about). So as soon as I have a little spare time expect a flurry of activity here.

I've been writing some Java 5.0 code recently and, much as it pains me to admit, it's growing on me. I still think the biggest problem with 5.0 (aka 1.5) is the fact that 5.0 code looks like a different language. It's all those angle brackets.

But despite changing the face of Java code as we know it, generics turn out to be a real productivity win. And no, it's not the faux type safety you gain, but rather the fact that your IDE can autocomplete the members of the type you just hauled out of your hash table. You get to write

String myProperty = myMap.get(myKey).getPropertyValue();

instead of

String myProperty = ((String)myMap.get(myKey)).getPropertyValue();

The latter almost always involves jumping around with arrows keys and filling in more brackets than is sensible. The other thing the astute will notice is that I'm starting to use the Sun coding conventions. Bit of a change for me but they're not as intolerable as I thought. Just take a bit of getting used to.

Swinging our focus back onto 5.0, I'm also getting a fair bit of usage out of the "foreach" construct. This one still annoys me, for two reasons:

  1. Rather than using a keyword (which would have fitted more easily into the existing Java landscape) Sun chose to use a colon as part of this construct. While vaguely in line with the standard for loop it just seems a bad fit to me. You end up writing code that just looks like it doesn't fit. Would an in have killed them? I'm pretty sure it could be slotted unambiguously into the language grammar.
  2. As useful as it is, when it comes time to walk through a collection looking for items to remove you have to fall back to a bog standard iterator. Which means you end up with two different looping constructs (often for the same collection) in your code. This sits badly with me.

Enumerated types might have been handy if I weren't writing a lot of throwaway code at the moment. I have yet to encounter a real need for autoboxing. Given the sheer volume of Java code I've written in the past week this is quite suggestive. To be honest, I've never really felt a gaping hole existed here. Oh, and I've yet to import a static type. I like that my constants live in their own namespace.

Posted at 10:52 PM

Ramblings

Urg. I feel terrible. I finally got my act together and went for a proper massage yesterday. True to form (at least in Cape Town) it turns out I did Tai Chi briefly with her (we ran the "sports? university?" gauntlet until we figured out why we looked so familiar to each other).

I felt great afterwards. Today is a different story. She warned me to drink lots of water which I duly ignored (yesterday), apart from the token bottle when I got back to the office. Today I drank every millilitre I could fit in (and in the process burned a permanent track out to the bathrooms). I'm booked in for another appointment next week but if tomorrow isn't an improvement I may have to jump the gun.

In other news, Fommil (perhaps that will repay him) dropped me a note to point out that greenfi wasn't producing any significant hits on Google, so he linked to me under that pseudonym (jgreenfi was my unix login at varsity and it seems to have stuck). Google duly indexed his link (all praise Google) and now it seems that this page shows up as the first link if you search Google for greenfi.

Fame and fortune at last ;-)

Posted at 07:21 PM

Cueball

All it took was a brief moment of inattention and a slip of the hand.

Yesterday I sat down for my bimonthly shearing. Without really thinking about it I handed the electric razor to my lovely assistant, forgetting that I had yet to attach the number 2 razor guard. Like me, she failed to perform a sanity check on said equipment and the next words I heard where along the lines of "Oh dear, is it supposed to take so much hair off?"

Erm. No. No, it's not.

Follow with some deft handiwork with the number 1 guard and, nore more than ever, I'm in touch with my inner cue ball.

Posted at 08:12 PM

Ceres-ly good riding weather

ceres_small.jpg Very pleasant ride today, despite a bit of a shaky start.

For some reason I was up with the first sparrow's fart this morning. Just as well: I was meeting Riel Ferrous Gluteus Maximus Smit at 8am for a ride and I'd forgotten to set my alarm clock (or rather I'd painstakingly set it the night before but forgot to activate it). The first time I started the bike this morning there was a brief hiccup and I noticed it had reset the clock. "Odd" I thought, but paid scant attention when it started without a hitch second time around. When I met up with Riel however, things didn't resolve themself quite so quickly. The bike refused to start. It sounded like the battery was completely flat. Admittedly, I did leave the lights on while waiting for him to arrive, but that couldn't have been more than 10 minutes.

So we had to resort to push starting it. I'm not sure who was more surprised: me or the bleary eyed cyclist who suddenly found himself on a collision course with a silent red motorbike. Somehow I managed the right combination of declutch, rev, reclutch brake required to jump start the engine (first time!) and not kill the cyclist. After that we were all systems go. This is the kind of biker Riel is: let's push start it now and head out. Who cares if we have to push start it after every stop. No sweat. You have to admire spirit like that. It did mean I spent the remainder of the ride waiting for the bike to fail to start. It never did and the ride itself was very pleasant. Riel knows the Western Cape like the back of his hand so riding with him is always a pleasure.

Total distance was around 350km. Not a bad morning's ride (but not a patch on Riel's average ride). We had breakfast at the bottom of Bain's Kloof pass and then stopped in Ceres (inset) to top up (the bikes, not ourselves) before heading through to Worcester. A brief stop there for some water (and to debladder) and then home.

The ride also added to my list of registration plates (yes, I know, I'm an anorak): CEX (Porterville) and CBM (Laingsburg). And Riel mentioned that what I'd thought was Grahamstown (CF), now part of the Eastern Cape, has in fact been reassigned to Brackenfell (up until now CFR), which explains why I've seen so many "Grahamstown" visitors lately.

Oy. Wake up. I'm talking to you.

Posted at 02:46 PM

Synchronicity and frogs

Weird case of something I thought was synchronicity but turned out to just be the Interweb in action.

One of the guys at work printed and put up a poster about a lost frog, just a day after I'd read about it on Sam's blog. I thought it was a pretty impressive coincidence but it turns out it was nothing of the sort.

I posted this entry which referenced Sam's blog. One of the other guys at work happened to read that entry and follow the link. Sam happened to have posted about the lost frog (here). Somehow this got forwarded to the poster at work resulting in the supposed coincidence.

Random is as random does.

Posted at 07:00 PM

Chalk up another headache

But I think I know what's causing them and, hence, what I need to do to stop them. After much soul searching and heartfelt introspection, I think it's time to limit myself to no more than four virgins at a time.

It's sad but it takes a real man to admit to his limits.

Last night was pretty bad though. I was struggling to use my touchpad with any real degree of accuracy because my right hand was shaking. That's new. I gave up trying to sleep at around 3am and went to find some strong drugs which ushered me into the land of blissful sleep. Which means I'm awake, have had very little sleep, and am nestled in the bosom of drug-induced somnambulance.

Posted at 09:40 AM

The apps are the API

It occurred to me today that there's a fairly fundamental difference between what you might call Un*x operating systems (including Linux) and Windows. I don't think I'm going to say anything new but perhaps I'll cast a slightly different view on it.

If I think about Windows, especially as a developer, then I pretty much view it as the win32 API. Uni*x, on the other hand, I view as a large collection of very specialised tools that I can very easily sew together. From a sysadmin perspective things are quite similar. Troubleshooting network problems on a Windows machine very quickly degenerates into restarting some services, but usually rebooting (with everything crossed in the hope the problem will "go away"). On a Un*x box things tend to be somewhat more deterministic (though not entirely). But even when you're really stuck there are dozens more tools for digging into a problem, especially networking tools (although this speaks to some degree to the pedigree of the two families of operating systems).

Coming back to developing though: this means you tend solve problems in two completely different ways. On Windows you generally write a lot of code. At best you make a few API calls, at worst you reinvent the wheel to a greater or lesser extent, often in a "full blown" language because the built in "scripting" support is pretty dismal. And for various reasons scripting languages like Perl, Python or Ruby are often only brought to Windows as an after though. And using them is often more painful than it needs to be because the OS has never really thought about how best to accommodate external scripting languages (although this is improving).

On Un*x you tend to pull together a few tools, mediating between them using some fairly powerful scripting languages. If the scripting language provided by your favourite shell isn't up to the task (rare) then Un*x lends itself well to plugging in other languages (#! is your friend). This is made even more attractive because at least one of (if not all of) Perl, Python and Ruby tend to ship as standard with many flavours of Un*x. Granted, I'm not extremely familiar with the API provided by Unix or Linux (I haven't done nearly as much serious development on either as I have for Windows) but I think the fact that for almost every system call in the man pages there's a system tool (usually of the same name) listed speaks volumes.

The different approaches grow different kinds of programmers. The Windows environment tends to make one wary of any sort of external dependencies, either because they tend to make your software fragile, or because hooking them up to your own software is usually horribly painful. The Un*x environment pushes you in the other direction. Plugging software components together tends to be very simple. This, coupled with the rich set of standard tools, tends to encourage reuse. There's also more willingness to suffer through external dependencies (which can make life difficult in any environment) but this tends to encourage better development because there's more though given to how things will play together.

A simple example from today: adding a few extra lines to a configuration file unless they're already present. On Linux this could be done using

grep -vq "New Config" some_config_file && echo -e "\n# New Config\nsome.var=some.value\n\n" >> some_config_file
I challenge you to do this on a standard installation of Windows. I'm not saying it couldn't be done, but I don't think it would be quite as pleasant (or quite as portable).

syslogd is another example. Get centralized logging (i.e. all logs end up on a single machine on the network) going for a collection of Windows machines without any additional software and for all applications. Admitted, the syslogd approach has some flaws, and there are some fairly big caveats, but as an entry level solution it's a great start.

Don't misunderstand me. This is not a "Windows sucks hoorah for Linux" rant. It's merely a reflection on the effect two different approaches to building an OS seem to have on development.

Posted at 10:42 PM

rpmbuild is my biaatch

So, as a matter of fact, is syslogd.

Whoever wrote rpmbuild needs some quiet time alone to contemplate what they've done. Actually, whoever wrote the rpmbuild book needs to do the same. Man, what a painful exercise. But it's done and dusted and we are now in a position to move onto centralized logging. Open source has a lot going for it. This is the third package we've had to modify to make it do our bidding.

In completely unrelated news, I have to share this comic with the world. It's terrific, especially the occasional view into the central character's "tortured" home life.

Posted at 09:39 PM

httpd.conf and Superman the tour guide

Weird combination of dreams last night. First up was Apache. While I was editing httpd.conf someone rolled over my mouse hand (I think they were asleep) which resulted in me pasting the entire contents of the X windows buffer into vi. Needless to say, chaos ensued and one of the key combinations pasted into the window was ESC:q leaving me with a corrupt file. Oh woe is me.

The latter half of the dream, which made up the bulk of it, featured me in Oz with a group of friends. Two of us were moving out there (not sure why) and I ended up being the designated tour guide for our group. Only I had super powers, which meant I could leap buildings in a single bound. I spent most of the dream doing this (it's great fun, trust me).

Posted at 08:11 AM

The Collatz conjecture

In between writing (and occasionally testing) code we're interviewing anyone we can get our hands on who looks vaguely promising (yeah, in some ways it feels like I never left ;-)

I was prepping for a phone screen today and grabbed an internal list of questions looking for something interesting I might be able to use. The first option I came across that caught my eye looked like a great question, especially since I thought it had an easy answer. So I sat down to tackle it (never go into an interview unless you have a reasonably good feel for the questions you're going to ask). The question was pretty simple:

Define a sequence T as

T(n+1) = { T(n)/2     if T(n) is even
         { 3*T(n)+1   if T(n) is odd
and define the length of this sequence as k such that T(k) = 1.

Given a range of input values [x..y] compute the length of the longest sequence (and indicate which of the input values generated that sequence).

If you only consider powers of two (which as a programmer tend to jump out at me) then this looks trivial: they just divide away to 1. And since an odd number will always generate an even number it should just be a case of transforming any odd numbers into their respective even numbers and then taking the highest number. The length of the sequence is then just log2n. Right? Wrong. I fell (quickly) into the silly trap of treating all even numbers as powers of two.

Fortunately someone more familiar with the question stopped me before I spent the rest of my natural life on it. It turns out this is the basis for a well known (and open) conjecture in modern mathematics, the Collatz conjecture, which postulates that this will always produce a terminating (i.e. finite) sequence. It's been shown to hold for n up to 27,021,597,764,222,976 (approximately 27 zillion), which is probably enough for the average Computer Scientist (except people looking for another distributed computing problem to hack away at) and waaaay more for most Physicists (who would have assumed it holds for all numbers because it holds for one through ten).

Posted at 08:34 PM

Walking in the forest

trunk_small.jpg We've started walking in one of the nearby forests on Sundays. The intention is to do this as regularly as possible, in an attempt to combat our sedentary lifestyles.

I enjoy these walks, but for an altogether odd reason. We live in a particularly spectacular part of the world, and walks like these give me a chance to take pictures that I hope make people like Sam jealous.

For some reason on this particular walk I was far more aware of the smells of the forest, and in particular the fynbos fighting its way through the invaders. Those smells take me back to the occasional mad scrambles up the mountains bordering Fish Hoek while I was at high school. A mountain, two male teenagers, a competitive spirit. All these add up to only one thing: exhaustion :-)










Posted at 06:26 PM

Build dependencies

Yup. What could be more exciting than that? Despite the apparently dry subject material I got almost no sleep last night because my head was filled with build dependencies and thoughts of repository (depot for Perforce users) structures. I think my queues are full and my brain is frantically trying to process their contents so they can be put into cold storage.

I usually struggle to sleep when I'm concerned about something. Sometimes "concerned" is probably too strong a word. Often the cause is something I feel a strong need to tell someone the following day. I suppose I'm worried I'll forget so I go into a kind of busy wait trying to make sure it never goes out of scope.

Sometimes I go to bed with something like this queued. But often it's some "revelation" that occurs to me during the tossing and turning process. When this happens I usually spend the night muttering about it like a crazed lunatic after a night of particularly heavy binge drinking. The really odd thing (maybe that should be "another odd thing") is that I'm usually vaguely conscious that I'm talking about it.

Yesterday was a case in point: when I surfaced into the morning sunlight, complete with bloodshot eyes and fatigue poisons still coursing through my veins, I knew I'd spent the night talking about Perl closures (this was quicky confirmed).

Posted at 09:19 PM

Build dependencies

Yup. What could be more exciting than that? Despite the apparently dry subject material I got almost no sleep last night because my head was filled with build dependencies and thoughts of repository (depot for Perforce users) structures. I think my queues are full and my brain is frantically trying to process their contents so they can be put into cold storage.

I usually struggle to sleep when I'm concerned about something. Sometimes "concerned" is probably too strong a word. Often the cause is something I feel a strong need to tell someone the following day. I suppose I'm worried I'll forget so I go into a kind of busy wait trying to make sure it never goes out of scope.

Sometimes I go to bed with something like this queued. But often it's some "revelation" that occurs to me during the tossing and turning process. When this happens I usually spend the night muttering about it like a crazed lunatic after a night of particularly heavy binge drinking. The really odd thing (maybe that should be "another odd thing") is that I'm usually vaguely conscious that I'm talking about it.

Yesterday was a case in point: when I surfaced into the morning sunlight, complete with bloodshot eyes and fatigue poisons still coursing through my veins, I knew I'd spent the night talking about Perl closures (this was quicky confirmed).

Posted at 09:19 PM

Perl closures

After all the Ruby ranting recently it came as no surprise that last night involved at least one pretty active REM cycle. For some reason though, my dreams were of closures in Perl rather than anything directly related to Ruby.

Go figure.

Posted at 10:34 PM

More Ruby "goodness"

I have to admit to a brief moment of "hey, this might actually be quite cool" while playing with Ruby today (some of the iterators, like collection.select, are handy). But it was very brief.

I'm working my way through Programming Ruby: The Pragmatic Programmer's Guide on the side. The authors are so obviously pimping Ruby it's hard not to laugh. Sometimes it borders on the ridiculous.

It annoys me that Ruby has gone the route of abusing punctuation instead of using sensible keywords. This comes back to my argument that code is generally read many more times that it's written. But the least they could have done was be consistent. Inheritence is expressed using the < operator, but mixins (read multiple inheritance, and see below before you shout me down here) are expressed using the include keyword.

Which leaves us with throw and catch. Ruby resurrects a construct long thought to have been banished from most sane code. Yup, that's right, it's goto in disguise. The idea is that you can wrap a block up in catch with a 'symbol' (read label) and anywhere within that you can throw that symbol and jump straight back out to the top-level catch. This just screams "Abuse Me!"

One of the "big features" Ruby apparently has on offer is mixins. This is supposed to be all the benefits of multiple inheritence with none of the drawbacks. Unfortunately, as far as I can see, this is just bullshit. It's essentially multiple inheritance with all of the associated problems. Don't believe me? Try the following piece of code out.

   module Foo
      def do_foo
          @member = "foo"
      end

      def test
          "Foo.test"
      end
   end

   module Bar
      attr :member
      def do_bar
          @member = "bar"
      end
  
      def test
          "Bar.test"
      end
   end

   class FooBar
      include Foo
      include Bar

      def initialize
          do_bar
          do_foo
      end

      def test2
          "Hey: " + @member
      end
   end

   f = FooBar.new
   puts f.test
   puts f.test2

   f = FooBar.new
   puts f.test
   puts f.test2
This produces the following output:
  Bar.test
  Hey: foo
The book itself says it best: "There's a risk here, of course, that different mixins may use an instance variable with the same name and create a collision ... <so> ensure that the instance variables have unique names to distinguish them from any other mixins in the system (perhaps by using the module's name as part of the variable name)". Erm. Sure.

And the book. What can I say about the book. At the very least it gets annoying at times. For example, it's laughable the way the authors present exceptions as this new space age solution. <bad french accent>Return values? I blow my nose at your return values.</bad french accent> Guys: newsflash: a whole host of languages have been doing this. Some of them for many years already. Exceptions are a Good ThingTM but they're hardly news. Get on with it. While we're on the topic, why the hell do we have to have yet another keyword for catching an exception? Python did this too with except and Ruby's done it again with rescue. But just in case you aren't paying attention, there's also a catch but it doesn't do what you think it does. Or rather it does, kind of. In Ruby we have raise (consistent with Python) and rescue (consistent with, er, shit, nothing).

And the idea that

   3.upto(9).each ... { blah }
is somehow "less error prone" than
   for(i = 0; i < 9; i++)
is just stupid. Both are equally error prone. Both are subject to off by one errors. Quick, does upto include the value specified or not? Not sure? Yeah, you probably want to look it up to confirm. Until you have that committed to memory, the first example may even be slightly more error prone. The second example has the advantage that it's idiomatic in a few languages (C, C++, Java, even Perl). That's a lot of reusability. upto? How much reusability there?

And they're really pushing this "natural Ruby way of doing things". Sometimes to a silly degree. The section on "Containers, Blocks and Iterators" has a subsection titled "Blocks and Iterators" which introduces a loop that searches a list for an item. After expressing it using what amounts to a for each construct they suggest "What could be more natural?" only to state "It turns out there is something more natural." Huh? Firstly, "natural" is a personal preference. But more importantly, if it were more natural then why did you lead in with a completely different solution? See for yourself (search for "what could be more natural")

For the record, I'm not suggesting that Ruby is considerably worse than, say, Perl or Python. I'm just very disappointed. After all the hype, everything I've heard and read, the reality of it is a real let down.

Posted at 07:34 PM

A first look at Ruby

I took my first look at Ruby today. It's not imperative that I learn it right away. We're actually developing in a few different languages but I'm sufficiently conversant in the others (C++ and Java) that I'm confident I could be up and running with any of that code quite quickly. Ruby is the dark horse at the moment. But it's been pushed quite hard by a number of people (some of whom I even trust) and it really has garnered quite a bit of press lately. So I've actually been toying with the idea for a while now.

So far though, I'm less than impressed. There's a distinct lack of any warm fuzziness. I'll be the first to admit, though, that I've only scratched the surface. So anything written here should be read bearing that in mind. And this is probably coloured by the usual frustration of learning a new language: having to look every second thing you want to do up. This will pass as I start to get inside of the mind of the Ruby author (ouch) and is something I've experienced with every language I've picked up (save Perl oddly enough, which is probably a pretty serious indictment). With all that said, let's take a closer look at some of the "features" Ruby has to offer.

Everything is an object: This is usually one of the first things Ruby pimps raise. Frankly, so what? So everything's an object? How does that benefit you? In languages like C# and Java this applies to enough of a degree that the difference is immaterial for most practical purposes. Yes, blocks and closures are objects but this smacks of delegates (so C# can do this too). Interfaces are a much safer way of managing callbacks. And if you really want delegates in Java then you can always abuse the reflection API and build a delegate of your own using an instance of the Method class. But, cry fans of the language, you can create arbitrary blocks and they're treated as objects too. Uh huh. This means you can do this:

   myblock = {
     puts "Look ma, no hands!"
   }
   doSomethingWith(myblock)
Woohoo. Not exactly a major win in my books. Ah, but Ruby lets you do all of this in less code than Java or C#. So? How often is this actually a good idea? In code that will live on for a decade? In code that needs to be manhandled by 50 programmers? 500? 5000? Most "productivity enhancements" I'm seeing touted at the moment save typing. This is not a productivity boost unless you're the only person working on your code and it never gets over a few thousand lines long. Code is read far more than it's written. Even taking into account changes as code is fixed or evolved. More eyeballs will spend time trying to figure it out than fingers will ever spend writing it.

Closures: I'm not sure what it is about lexical closures that seems to have made them the central figure in every second programmer's nightly wet dream. For those with clean sheets closures are basically anonymous blocks that "capture" the context they're defined in and can be executed by a caller elsewhere (or elsewhen). Frankly I haven't yet seen a compelling argument for this. And don't say callbacks. All you need for that is either something along the lines of interfaces, or delegates (or function pointers). Capturing things defined within the local scope of the closure is useful for parameterizing the logic you're about to throw all over the place, but again, this isn't something you can't do with an anonymous inner class or a delegate.

One of the big things pushed here seems to be that there's far less syntax involved. This is supposed to make it more likely that you'll use them. I don't believe in designing a language around this kind of argument. Frankly, the IDE should take care of that kind of thing. If your language design tries to compensate like this you end up with write-only code because you go out of your way to reduce perceived verbosity. This usually means favouring all sorts of implicit nonsense (Perl is famous for this) and you start using punctuation instead of keywords (again, Perl took this to a new level, but C++ had a crack at it too). More on this later. The big push in the docs I've read so far around closures seem to be related to working with collections. Essentially you pass in a closure that operates on each item in the collection. Nice idea, except that most real world examples I can come up with need to modify the collection (filter it, reorder elements, etc). All of the examples I've seen so far seem to operate on the element alone, which usually means printing it. If you want to modify the collection, or produce a new one, then the closure needs access to something defined outside of the closure (like a new collection to put the filtered elements into). Fortunately closures can do this, but suddenly the caller needs an idea of what your closure is doing. It stops being a black box, which usually means it's usefulness decreases by an order of magnitude. Basically it turns into a (hard to maintain) toy. In the delightful syntax of Ruby you end up with something like this:

   filtered_list = []
   somelist.each { |item| filtered_list << item if (item == somevalue) }
The above is the "Ruby way" of doing things. The introductory docs I'm reading pimped the each method about half a dozen times within the first few paragraphs. Exciting stuff. Frankly:
   for item in list:
      doCrap(item)
is far more natural (and reads easier) than the "Ruby" way of doing this:
   list.each { |item| doCrap(item) }
Which brings me swiftly to my next point.

A simple syntax. Really? I've yet to actually encounter anything in Ruby that feels intuitive. Maybe this will change after a few days spent scratching my own eyes out. Ruby's full of little gems like the << operator above. Or the pipe operator for defining parameters for closures. And the "simple naming convention denotes the type of a variable" nonsense slays me: var is a local, @var is an instance member, @@var is a class member and $var is a global. The argument put forward seems to be "no more typing self or this". I've never once caught myself thinking "Damn, I wish I didn't have to type this. If only the language could do away with it in favour of an obscure naming convention". It gets better: method names have to begin with a lowercase letter. This isn't just a convention. The interpreter actually depends on these things and may parse your code incorrectly if you deviate. Sheesh. And then, just in case you're still climbing the hill, they go ahead and allow two punctuation marks (? and !) as part of a method name (with the convention that the former be used for "query" methods and the latter for "dangerous" methods or methods that modify their parameters). This is probably personal preference, but I don't like punctuation as part of an identifier name. We're trained from birth to split text on punctuation marks. Ruby's not going to undo that single-handedly.

It can't decide whether it's Python or Perl and it seems to have gone out of it's way to attract Perl programmers, even going so far as to propogate nonsense like implicit globals (badly named ones at that) like $_ for intermediate storage. Again, this is touted as a "feature" for the same reason Perl introduced it: it lets you do more with less typing. Which is usually another way of saying "lets you write unmaintainable code".

Ruby has also decided (like Perl before it) that one way to do things isn't enough. Perl made this popular, based on the idea that ten programmers will write the same piece of code ten different ways. The logic goes something like "well, if we can express the same thing in ten different ways then any given programmer is more likely to find the language a natural fit with his way of thinking". What it translates into is ten different programmers doing things ten different ways, producing large amounts of what a friend called "write-only" code.

And what's with puts? Why the hell does every new language feel the need to change something simple (and nearly universal) like the name of the routine that prints something to stdout? We've had printf, writeln, println, print and puts. Fucking choose one. Why does every language have to be different? This isn't a Ruby specific rant. It annoys me that switching languages has me fumbling with basic things instead of focusing on the real differences. With Ruby we have print and puts. The former doesn't include a line terminator, while the latter does.

Dynamic typing kicks your tools in the nuts. Goodbye auto-completion. Goodbye refactoring support. Want to rename a method? %s/oldname/newname/g and lots of testing. And that assumes its in a single file and there are no name collisions. Ruby has turned Eclipse into a bloated version of notepad. As far as editing Ruby code is concerned, it's currently about as useful as Microsoft Word.

And there are all the other little things that so far haven't endeared Ruby to me. The interpreter is about as useful as Python when it comes to error reporting. It'll just about point out the line of code that it doesn't like and tell me there's a syntax error. (Somewhere there. Left, left. Right. Yes, there! What? No, I'm not going to tell you what's wrong). And even at version 1.8.2 we're seeing stability issues, which isn't going to win friends.

It's not all bad. I like the native regular expression support (much like Perl's), although I think it lends itself to abuse just as it did in Perl. But overall I'm not blown away. And I certainly don't feel like I'm working in a language with a cleaner syntax. Java made C++ syntax feel overly-complicated. Ruby's done nothing of the sort, for any languages I know.

Hey, nowhere to go but up. Right?

Posted at 07:45 PM

Little old ladies

At the moment I feel a little like the proverbial little old lady. You know, the one that seems to have owned every second hand car on the market (the one who only ever drove it to the corner shop and back).

I took the bike out for a spin today. First time in a few weeks. In my defence the weather hasn't been great of late, and biking partners are scarce, what with Andy's bike in for repairs (and possibly Andy too by the look of things), Matt's being in to fix the oil leak (again), Riel being more dedicated than me (and hence out most weekends on considerably longer rides than I'm up to right now), and Werner and Albert, well, living large in lunatic land.

Today's run was short because we squeezed in a walk in Newlands forest. But I managed to get out to Stellenbosch and scream ... er, I mean putter along sedately ... along some of the back roads out that way. The weather was gorgeous. With luck this means it's finally turning. We've had a few false alarms in the past weeks. If I believed in God I'd suggest he was having a field day screwing with our small minds.

My license expires pretty soon. Which means sitting for the test again. I'm still on a learner's permit (many people do this for decades, you just resit the test every 18 months). When I get around to it I'll book for the full rider's test but I can't really be bothered right now (queuing at the traffic dept isn't my idea of a great way to spend a morning) and there's a backlog of at least a few months (for both tests) so I've plenty of time even if I do book it now. I had a brief moment of panic this morning when I remembered I had a booking in October but couldn't remember when (raising the possibility that I'd missed it). The next available slot is in early January, or was the last time I looked.

Fortunately I haven't missed it. I'm booked for Friday morning. That's the other great thing about most government services in this country (and others to the best of my knowledge). You can almost imagine someone somewhere going "I know! Let's force productive hard-working (ahem) people to take time off during the week to get these things done."

Posted at 10:31 PM

Keeping it tidy

plaaskuns_small.jpg Andrew was in town for the weekend. He's one of the running nutters that seem to inhabit my world.

Caught up with him and a handful of others for drinks at various points this evening (squeezed Sin City and dinner in between). Most watering holes are too loud to have a decent conversation. Having a draught or two inside you doesn't help either. Trying to talk sense with Andrew is the final nail in the coffin ;-)

Other people are easier to talk to (really talk to). I suppose at some fundamental level things just gel better than with other people. That helps in getting past the "er, hell, there's nothing in my queue but technical crap" and the "bugger, I've run out of witty things to say" (assuming you had any to begin with). Hey, I'm a member of a subset of the population that's known for a lot of things that don't include social interaction. But these people are few and far between and I'm a lazy friend (shame on me) and usually too wrapped up in my own world to even notice that I'm being a lazy friend.

So if you think you fall into this category, next time you see me slap me and tell me to get off my ass and do some catching up.

Ooh, this is going to come back and bite me.

Posted at 01:10 AM

Dinner with friends

cshons_dinner_tim_and_sandra_small.jpg Tim and Sandra were both in town. Tim's was only around for a few days but Sandra is back indefinitely.

We took this opportunity to get some of the old crowd back together and had dinner just up the road from here. Much to my embarrassment I forgot to invite bwong and strimble. Sorry guys. My only excuse is that I assumed the message would propogate out (and Steve I honestly thought you were in Joburg for some reason).

Dinner was too short to really catch up but definitely long enough for Tim to regale us with some new opinions.

We really need to think about a proper get together. It's been way too long and it was easy to let it slip by while I worked with almost a third of them.

Posted at 12:04 AM

Apportioning blame

I played with Subversion for the first time today. Subversion is intended to be a "logical" replacement for CVS that doesn't force CVS users to throw away their existing mental models but at the same time fixes some of the more annoying problems with CVS.

Knowing this I haven't really been looking forward to playing with Subversion. All prior experience with CVS has left me feeling violated and in need of a cold shower. Frankly, Perforce has spoiled me. I'd argue that it's one of the best version control systems out there, but I can't back that up with enough experience to make it a reasonable claim. But I can say that in over five years of use Perforce always did what I expected and never once got in my way. Oddly enough, apparently Amazon uses Perforce, even if Amazon ZA doesn't (licensing issues coupled with a desire to keep everything we do open source).

After resetting my brain and playing for half an hour Subversion is starting to feel pretty natural. I'm curious to see what GUIs exist. Yeah, I know, GUIs are for pansies but frankly while the command line was useful the Perforce GUI made source control a no-brainer. I've watched too many people over the years sneer at the idea of using the Perforce GUI. Almost without exception these are the same people I've found myself chuckling at at a later point in time when they lament the fact that they nuked something important unintentionally. Why? Usually a combination of the command line tools and one (or more) itchy trigger fingers.

But, the first thing everyone at the office mentioned about Subversion was the equivalent of p4 filelog (lists the revision history of one or more files). Subversion's equivalent? svn blame.

For people who prefer to foster a positive environment, an alias exists: svn praise.

Geeks have a singularly unique sense of humour.

Posted at 07:21 PM

Ping

I broke about as much software today as I did yesterday. Who knew I was a closet member of QA?

But, today ended with me frantically scrambling to just finish one last change before I had to dash off to Tai Chi. And I can't wait to get stuck into it again.

All of which I take as a positive sign.

Posted at 07:53 PM

Life in the ... er ... um ... lane ...

Day one. In some respects pretty frustrating, but that was inevitable. I'm all thumbs with this Loonux thing. Damn new-fangled technology.

Seriously, although I can find my way around a Un*x OS (or an OS like Linux that pretends to be Un*x) every distro does things differently. Scratch that. Every version of every distro does things differently. Sometimes I wonder if they have no new ideas and are dedicating entire teams to finding new places to put configuration scripts.

Needless to say it's going to take a while to get up to speed. In addition, it's new hardware. It's amazing how used to a keyboard you can get. So that will take a little while to come right too. And then there's figuring out all of the infrastructure and finding my away around the LAN. And this is even before starting to figure out the codebase I'm now part owner of and just how all of that fits together.

But I'm reasonably happy with my progress. Baby steps and all that.

The guys I'm working with are generally great. They're all pretty clued up, they're all loud and opinionated (I'll fit right in) but most importantly, there are no egos floating around. People are quite comfortable asking for help or admitting they don't know something. Makes it much easier when you're in the throes of getting up to speed.

I did have a minor epiphany today. The environment at work is pretty chilled. Everyone has a truck load on their plates but it just doesn't feel tremendously pressured. Or at least not in the same sense as it was at Mosaic. It actually feels a lot like the early days at Mosaic. This got me thinking. I've always had a sneaky suspicion that the tremendous stress the teams at Mosaic are under is in part due to Mosaic's size. Mosaic's size coupled with the direct communication channels between various teams means that every team has a proportionally higher number of "stress generators". In a team of ten devs how many people can possibly generate any form of stress (in the form of questions, dependencies, broken code, etc) for you? If the team increases to 50 devs things look quite different. Suddenly instead of 9 possible sources of stress during the day you have to face 49. That's a significantly different environment.

In short, size does matter. Yes, yes. I couldn't resist.

Posted at 08:23 PM

All's well that ends well

Just finished archiving the last 5 years so I can return the laptop I've lived on for most of recent history.

We are go.

Posted at 10:07 PM

On laptops and import duty

Mr C is back in the country along with my new toy. Unfortunately he didn't quite manage to pull off the "Smuggler? Me?" at customs and was forced to pay 20% duty and a 25% fine. Still, the laptop comes in at about 25% less than I'd pay for it here.

But it grates giving SARs any money, especially when it's blatantly obvious that very little of my tax money is being spent appropriately as it is.

Bah.

Posted at 07:43 PM

Life, Landrovers and Everything

mosaic_whiteboard_small.jpg A real onslaught of twists and turns last night. I think my brain is trying frantically to process the last 5 years and prep me for new stimuli.

It began (as far as I can recall) in an Internet cafe, I presume in London because we paid in pounds. The total came to 65 quid for three of us. I remember that we could make exact change for 60 quid (although the amounts put forward actually didn't sum correctly in retrospect) but had to break a 20 to make up the rest.

From there we went out for a walk. I don't remember much from this segment. Only two things stand out: leaving an opera house and someone I was seeing very briefly a couple of years ago telling me they loved me. Someone who would probably battle to admit that to anyone (I did query whether or not it was a joke in the dream). I remember distinctly thinking "Does that mean the engagement's off?"

From there it was onto a dusty road to drive into the middle of nowhere to wish someone happy birthday. Someone else was driving, but I'm not sure if it was the third person from the Internet cafe or a newcomer. We rounded a corner and saw the road was fairly heavily flooded. This didn't stop our driver who ploughed on valiantly. It was too much and our landrover came to a stop in water up to the windows.

Cut to the side of the road where we're watching other motorists round the corner and meet the same fate. I remember a BMW almost making it and then stalling. At one point I tried to take a photo but my damned flash wouldn't fire and it was dusk so the picture was useless.

We retired to Skippy's parents' lounge to try to repair the engine but it turned out a part we needed would take days to arrive.

And then I woke up.

Posted at 10:22 AM