November 08, 2009

Behind the scenes at the opening of the Berlin Wall

BBC News: How a blunder finished off the Wall: “Mr Schabowski's announcement was complicated and bureaucratic, and like many others that evening I puzzled over it before concluding that it signalled free travel… East Berliners were rather quicker off the mark. Tens of thousands of them started turning up at the border demanding to be let across.  But the guards hadn't been told anything - their standing orders were to stop anyone crossing. Until recently they'd been instructed to shoot to kill anyone who tried… The guards asked their headquarters for orders but the government ministries in charge of security told them nothing… The guards on the ground - at the time - made the critical decision. They ignored their standing orders. They said, ‘Open the border.’”

The 1989 “carnival of revolutions” is a story I will never get tired of hearing.

November 8, 2009 | Permalink | Comments (0) | TrackBack (0)

October 31, 2009

Units of measure in F#

The latest version of F# introduces units of measure.  Using this feature, you can indicate that a numeric value is in a particular unit – metres, seconds, etc. – and the compiler will track that as part of the data type and validate that units are being converted and compared correctly.

For example, we can declare the following values:

let distance = 1000.0<m>
let time = 400.0<s>

Give these the ol’ Intellisense mouse waggle, and you find that distance has type float<m>, and time has type float<s>.  Try to add them together, and you get a tasty compiler error:

let nonsense = distance + time

FS0043: The unit of measure 's' does not match the unit of measure 'm'

But divide them and the compiler recognises that it makes sense, and figures out and tracks the derived unit of measure:

let speed = distance / time

speed has type float<m/s>, and again the compiler enforces that operations on speed are compatibly typed:

let description =
  if speed > 10.0<m s^-1> then
    "fast"
  else
    "slow"

Notice that F# supports the Proper Science notation of negative exponents as well as the Way Everybody Really Does It of division notation.

Derived units of measure can have names: the type float<kg m s^-2> is the same as float<N> and values of these types are therefore compatible.

let mass = 1.0<kg>
let accel = 50.0<m/s^2>
let whompiness = mass * accel

let ouch = whompiness > 100.0<N>  // compiles

Where do units of measure come from?  Well, when a daddy unit of measure and a mommy unit of measure love each other very much… but we’ve already talked about derived units of measure.  In fact, there are no units of measure built into the F# language or core library.  So either you have to define the units you need using the MeasureAttribute:

[<Measure>] type m

or you can import a bunch of standard SI units (basic units like the metre, kilogram and second, and derived units like newtons) from the F# Power Pack DLL:

// after referencing FSharp.PowerPack.dll
open Microsoft.FSharp.Math.SI

The Power Pack also includes a bunch of physical constants:

open Microsoft.FSharp.Math

let description =
  if speed < PhysicalConstants.c then
    "it's science"
  else
    "it's science... fiction!"

Naturally, these are all declared with the correct units of measure so efforts to compare Planck’s constant to the speed of light will meet with ignominious failure.  To work around this, tell your boss you need $370bn for a new particle accelerator.

To be clear, F# doesn’t assign any actual semantics to units.  For example, if you declare imperial units (because if it was good enough for the Babbage Engine, it’s good enough for the CLR, by Jove):

[<Measure>] type ft

F# won’t let you combine feet with metres.  It has no way of knowing that ft is a length measure, or how it would convert to metres.  However you can of course create conversion functions for your units:

let feetToMetres(f : float<ft>) =
  f * 0.3048<m> / 1.0<ft>
let totalLength =
  100.0<m> + feetToMetres(100.0<ft>)

Notice that our metres-per-foot expression spells out 1.0<ft> rather than 1<ft>.  F# only allows units of measure to be applied to floating point values, not integers.

Finally, be aware that units of measure are erased during compilation.  At runtime, F# (or rather the CLR) sees only plain old floats.  Unit checking is part of the compile phase only.

October 31, 2009 in Software | Permalink | Comments (0) | TrackBack (0)

October 24, 2009

If only he really had been

Shorter Nick Griffin: “Being asked questions by the public makes me the victim of a lynch mob – quite unlike people who’ve been beaten up or murdered by gangs of BNP thugs for having the wrong colour skin.”

October 24, 2009 in Current Affairs | Permalink

October 01, 2009

Crushing souls for fun and profit

The BBC commemorates – I won’t say ‘celebrates’ – 25 years of PowerPoint.  And the statistics are alarming.

The average PowerPoint session, apparently, runs for 250 minutes.  More than four hours!  I still feel bad about a presentation that overran to an hour and a half.  I’d like to say I can’t imagine what it would be like to sit through an “average” 4-hour PowerPoint session, but I can.  All too clearly.

And the average PowerPoint slide shows 40 words.  Admittedly this figure is distorted by a former colleague, the splendid Jane Smith, whose average PowerPoint slide showed 265.4 words, but surely even Jane’s prodigious output can’t account for more than 0.07 of that average.

Anyway, the article does also offer a few basic tips on the dangers of PowerPoint and how to avoid them (plus, from the comments, the delightful coinage “PowerPoint karaoke,” which I am officially adding to my vocabulary), and I’ll throw in one anecdote of my own.

A few years back I did a “training the trainers” course.  Although this was well into the PowerPoint era, the lady who ran the course did all her slides on printed transparencies on an old-skool overhead projector, and made us do the same.  How strange, we thought: if you were projecting off a laptop you wouldn’t need to faff around taking one slide off, putting it carefully down, transferring the protective tissue paper to the other side and placing and adjusting the new slide on the projector.  You could get straight onto the next slide and completely avoid all that delay.  Ah, she explained, but the time between slides was an open space.  You, and your trainees, could and should use it to invite questions, discussion or just reflection.  The slow turnaround between slides wasn’t a bug.  It was a feature.

In that moment, I became enlightened.

October 1, 2009 in Usability | Permalink | Comments (1) | TrackBack (0)

September 20, 2009

Monopoly goes to war

More news of board games in World War II: “Before leaving for missions, British airmen were told that if they were captured, they should look for escape maps and kits in Monopoly boards and other games delivered by charity groups. They were told that ‘special edition’ Monopoly sets would be marked with a red dot on the free parking space… In addition to [a] concealed compass, tools and maps, real bank notes were hidden under the fake money.”

September 20, 2009 in Games | Permalink | Comments (0) | TrackBack (0)

September 17, 2009

Cease this nonsense at once

Popped into the supermarket last night and there at the front of the shop was a display of festive wrapping paper and Christmas trees.

For goodness’ sake, it is the middle of September.

This is going to be a very long spring.

September 17, 2009 | Permalink | Comments (2) | TrackBack (0)

September 15, 2009

Code Camp Auckland - .NET languages talk

Thanks to everyone who came to the Auckland Code Camp, to all the speakers and especially to the hard-working organisers! Here are the slides from the .NET languages talk:

What's happening in .NET languages - slides (PPTX format)

The demos were basically pretty closely derived from the Expert F# book and can be got from the book's Web site.

September 15, 2009 in Software | Permalink | Comments (0) | TrackBack (0)

TechEd 09 - Visualising data in Silverlight and WPF

Thanks to everyone who came along to the Silverlight and WPF session yesterday. Unfortunately the final demos got a bit rushed but here's the complete code to all the samples which I hope will make a bit more sense when taken with a bit more leisure!

Visualising Data in Silverlight and WPF - slides (PPTX format)

Visualising Data in Silverlight and WPF - demos

September 15, 2009 in Software | Permalink | Comments (0) | TrackBack (0)

September 06, 2009

Sunday “cats in domestic appliances” blogging

With only a week to go until Code Camp Auckland, it has been “all hands on deck” to help polish my presentation for the big day.

All paws on keyboard, anyway

I even had a volunteer to write a Perl demo.

Quickest way to write a Perl program

September 6, 2009 | Permalink | Comments (0) | TrackBack (0)

September 02, 2009

The case of the missing custom attributes

If you’ve used .NET a lot, you probably haven’t come across the Attribute.TypeId property.  This is the key – quite literally – to a problem that doesn’t come up very often – and by “not very often” I mean today I came across it for the second time in eight years – but should never have come up at all and is quite baffling when it does.

Let’s review.  .NET allows you to define your own attributes.  These attributes can be applied to types, methods, properties, and so on.  You can get at these attributes using reflection.  Life, in short, is good, at least for people whose desires extend no further than defining custom attributes and retrieving them again.

But .NET also has a sort of shadow type system: an early, hulking kind of dynamic type system tacked onto the side of the .NET 1.0 static type system.  It dwells in the System.ComponentModel namespace, TypeDescriptor is its herald, and ICustomTypeDescriptor is its tyrant king (and TypeConverter its capering fool).  The purpose of the shadow type system is to allow types to “adjust the truth,” adding properties that they don’t really have but are prepared to fake, and removing properties that they don’t want to talk about.  This is jolly useful.  It’s what supports, for example, making a Tooltip property appear in the Windows Forms property grid even though no control class actually has a Tooltip property, or applying Dynamic Data attributes to a property in one class by applying them to a field in a completely different class.

For 99.9% of the time – or, to be more exact, for 2920 days out of 2922 – the shadow type system works okay.  However, it does have some surprises up its sleeve, and one of those relates to custom attributes.  Specifically, if you apply more than one instance of the same custom attribute to a member, the shadow type system will randomly pick one of the instances, and throw the other one away.

Here’s an example.  Suppose we define a LocalDisplayNameAttribute class, which can be applied to a property to define a localised display name for a given culture:

[LocalDisplayName(“en-NZ”, “Sweet as”)]
[LocalDisplayName(“en-UK”, “Jolly good, old bean”)]
[LocalDisplayName(“en-US”, “WOO! YOU ROCK!”)]
public bool Yes { get; set; }

And now we ask the shadow type system for these attributes:

var prop = TypeDescriptor.GetProperties(type, “Huzzah”)[0];
var ldns = prop.Attributes.OfType<LocalDisplayNameAttribute>;
Console.WriteLine(ldns.Count());

This prints 1 rather than 3.  All instances of LocalDisplayNameAttribute except one have been discarded.

And this is where Attribute.TypeId comes in.

Attribute.TypeId has nothing to do with types, and very little to do with IDs.  It is misleadingly named, and misleadingly implemented.  Attribute.TypeId’s actual job is to answer the question, “Is this attribute instance a duplicate of this other attribute instance?”

Now the real type system has no problem with duplicate attribute instances.  It just stores the attributes and serves them up on demand, without passing judgment.  Hey, you wanted duplicates, you can have ’em.

The shadow type system, on the other hand, hates duplicates and makes sure to remove them during its process of “adjusting the truth.”  And it uses the TypeId as the criterion for doing so.  (Specifically, it uses TypeId as a dictionary key.)  And – and this is the kicker – the default implementation for TypeId is to return the attribute type.  Consequently, by default, the shadow type system sees all instances of the same attribute type as duplicates to be winnowed down to one.  In the example above, the shadow type system decided that the three LocalDisplayNameAttribute instances were duplicates and threw out all but one.

So, finally, we come to the fix.

If you’re creating a custom attribute which allows multiple applications, you almost certainly want to override TypeId to return a unique value for each attribute instance.  This could be a smart implementation which returns some appropriate combination of the attribute data, or it could just return a new GUID or even a this reference.

In the LocalDisplayNameAttribute example, as far as we’re concerned, there should be only one instance per culture ID.  If someone insists on supplying multiple local display names for the same culture:

[LocalDisplayName(“en-NZ”, “Sweet as”)]
[LocalDisplayName(“en-NZ”, “Choice”)]

then it’s choice and sweet as that the shadow type system recognises these as duplicates and dedupes them for us.  But we don’t want these en-NZ display names to come up as duplicates of other culture’s names and cause them to be discarded.  So our override of Attribute.TypeId looks like this:

public override object TypeId {
  get { return _cultureId; }
}

Parturient montes, nascetur ridiculus mus.  Well, better an easy fix than a hard one.

So what do you need to remember?

First, TypeId doesn’t identify a type.  It doesn’t really identify anything.  It answers the question, “are these two attribute instances duplicates?”

Second, if you’re seeing custom attributes go missing, TypeId is probably the source of the problem.

Third, and consequently, if you’re writing a custom attribute, and it allows multiple instances, you’ll probably want to override TypeId.

You won’t see this very often.  Unfortunately, when you do, the documentation is almost completely useless, and the default behaviour is more than a little surprising.  So file it away.  In 2013, you might just need it.

September 2, 2009 in Software | Permalink | Comments (3) | TrackBack (0)