A cavalcade of beer today! But drunk last weekend in Vienna in holiday mood, with cold wintery weather outside.

First, a warm bar called Centimeter, where many things (including sandwiches) were available by the centimeter. A Paulaner in its correct glass on the right, and I can't remember what the dunkel beer was on the left, other than this wasn't the correct glass for it. Both were delicious!

AustriaBeer1

Then, in a similar district we found ourselves in a big rambling place with its own brewery. I tried the chilli beer, assuming that it would deliver a warm background glow of chilli heat but nothing more, otherwise they'd struggle to sell much of it. I was wrong. This was throat scorching stuff and I probably wouldn't have another, but it was an interesting novelty experience.

AustriaBeer2
The Watercress Wildlife Association (a local nature reserve in St Albans), after the fresh snow this morning.

WWASnow

I saw a little egret, but it flew away every time I came within sight of it. So this is the best I managed.

LittleEgretFlying

I've stumbled across a real irritation with the way the Google App Engine data model works. One among many frankly, but I'll restrict myself to just this one for now.

The issue stems from the fact that db.run_in_transaction(func) insists that func is a function with no side effects, since it may be run repeatedly in an attempt to get the transaction to go through (if optimistic locking fails). Fair enough, but that means it has to freshly fetch any model objects that it wants to modify, otherwise it would have side effects to objects outside its scope. But consider this situation, in which we have an increment() function on our model object, that must use a transaction because it also modifies other related objects at the same time and require atomic behaviour:

class Person(db.Model):
  count = db.IntegerProperty(default=0, required=True)

  def increment(self):
    def tx():
      # Mess with some other related objects in data store.
      <omitted for brevity>
      # Must fetch a separate copy of self to avoid side effects.
      person = db.get(self.key())
      person.count += 1
      person.put()
    db.run_in_transaction(tx)

The problem here is that self hasn't actually been modified at all and is now out of date with respect to the data store (where the count is one bigger, assuming the transaction succeeded). This is a pain for the caller who had a Person object and called increment() on it and naturally expects their object's count to be one higher. But their object hasn't been modified at all – though the data store has, via the freshly fetched person. In case it's not obvious, we can't simply change the code above to use self instead of getting the new person object, since db.run_in_transaction(tx) may run our tx() function multiple times until it completes without an optimistic locking failure. If it did have to run multiple times, self's count would increment by one for each failed attempt, so the final successful attempt could end up with more than one added to the count. Or if the transaction eventually failed outright, self's count would still have been modified even though the data store had not been touched.

So the only solutions I can see are:
  • Put code after the run_in_transaction() call, that synchronises self with the data store. There isn't a sync() or refresh() method on Model objects, so you have to do this painstakingly by getting another fresh person with db.get(self.key()) and then copying across just the fields you know might have changed.
  • Insist that the caller is aware that certain methods on the model objects won't modify the object itself so they need to get a fresh one. This completely wrecks the idea of an object model and encapsulation though. You'd might as well just have a purely functional interface to the data store.
It all seems like madness to me, that defeats the point of trying to have a neat, simple data storage object model. As usual, I can only hope that I've missed some crucial point and that in fact the problem is easily and elegantly solved. I shall look out for that solution, unless some kind reader can enlighten me!

I recently bought a proper 'not tied for you in the factory' bow tie. Just a strip of wavy fabric to be assembled about my own neck! I figured I'd look (even more) dashing with the genuine article, tied just imperfectly enough to make it clear that it's the real deal. The instructions on the back of the box were frankly useless so I turned to Google and after a few pictorial, textual and video tutorials I got the hang of it:

BowTieTied 

It's not easy, and definitely requires a decent understanding of what you're supposed to do, then some practise until you can actually do it, followed by more practice to fettle it into looking half decent. It's worth being familiar enough with the procedure to be able to replicate it as necessary, since you may find some joker pulling yours undone at the ball! But my friends would never do that. And I had a backup pre-tied one in my pocket just in case.

My Marks and Sparks version came with an adjustable clasp in the middle, which is very useful to fit it to the neck properly and allows your hard fought bow creation to be saved for next time.

So, where are my instructions on how to do it? I shall cheekily defer to those that have gone before me, but humbly suggest that the easiest to follow description, and certainly the one that really sorted me out, can be found here: http://www.youtube.com/watch?v=VJv4Qh7zR3E

Of course the very best thing about a real bow tie is that you can do the 'just heading back to the yacht in Monaco harbour for a night cap' look:

BowTieUntied

I've just spent a pleasant long weekend in Vienna, Austria. A scenic detour through Belgium was required, to get us back to Blighty, EasyJet having forsaken us, but we did manage to get back whilst there's still some snow on the ground. I'm still going through the photographs (which are generally disappointing frankly) but I thought I'd stick this one up as a comedy teaser.

This shop's much bigger than it looks you know…

Tardi's

I do quite a lot of futzing around developing web apps, and as a result I'm often needing to choose colours to use in them, and I want those colours in HTML hex form – e.g. #ff0000 (bright red). The standard Mac OS X colour picker is a pretty reasonable colour picker, with all the features I want: colour wheel, RGB sliders, HSB sliders etc. but it lacks the most crucial feature – easy output of HTML hex codes! This is clearly a criminal omission, and it meant I'd frequently have to convert from RGB 0-255 numbers down to hex, which is tedious in the extreme.

Hence I was muchly pleased when I found Hex Colour Picker, which adds exactly this missing feature to the standard Mac colour picker panel. Perfect. Now I just open TextEdit, hit cmd-shift-c to bring up the colour panel and I have everything I need for web colour picking.

I've been banging away at my Google App Engine application. It'll be a little while yet, but in the meantime, a particular observation about Python. I keep getting tripped up when I refer to a member function without the parenthesis. For instance:

>>> list = [1,2,3,4,5]
>>> print list.count
<built-in method count of list object at 0x238fa8>

This doesn't print '5' because list.count is a reference to the count method itself, which (like everything else in Python) is an object, so gets printed. You need to use list.count() with those important parentheses in order to actually get the answer 5 that you wanted. I keep getting tripped up by this and taking a while to debug the problem every time. Some things like __class__ don't need parentheses, which I think is part of the confusion. Furthermore, when you use dir() to look up the public features of a class, it doesn't do anything to show you which ones are functions:

>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

I rather suspect I've missed a subtle but important bit of Python understanding, having only scratched the surface so far. If someone can point that out to me I'd be very grateful. 

I like witbiers and have always found Hoegaarden to be a classic example. It's a shame that it's another example of a decent beer getting bought out by the faceless mega-corporation – InBev in this case. Read about the history of Hoegaarden Brewery at Wikipedia.

Still, even with corporate types meddling it's a fine beer, with the citrus and spice flavours that you'd hope for. It's a shame it doesn't go a bit further with it though, to stand out from the crowd.

Hoegaarden

This is a tight crop of the front of the 'cable car' that runs up the hill in Wellington, New Zealand. It was absolutely bucketing it down, and windy too, so we never got to walk back down through the botanical gardens as we planned.

If you ever go to Wellington and look for the cable car, be aware that it's not a cable car in the sense that you might think. I think 'cable car', I think gondola's hanging from an overhead cable strung over pylons. Reality: funicular railway in tunnel. We spent ages walking the streets trying to find it, looking up in the air on the assumption that we could hardly miss it. The street map in the Rough Guide was wrong too, which didn't help.

WellingtonCableCar

My MacBook laptop has had to go in for repair as a sliver is splintering off the plastic palm-rest where the lid touches it at the edge. There are also myriad hairline cracks appearing in the bottom shell around the front and back. The repair guy I took it to assured me this wasn't my fault and that it would be covered under warranty, which is good since I've got less than a month left on the year long warranty. Phew!

It seems this has become a common problem and that Apple is sorting it out under warranty so I'd advise anyone else with similar issues to get it sorted.

It does mean I'm without laptop for much of this week though, which is a pain.

Update: It was indeed fixed under warranty but it took a bit of wrangling with Apple on the phone as they weren't keen. It all hinged on whether I had been treating it well or not.

Update 2 (April 2009): It looks like Apple is capitulating and more generally recognising and fixing the issue, even outside of warranty, if reports are to be believed – e.g. AppleInsider's report.