Instead of the usual Duxford/Saffron Walden/Balsham/Fulbourn sort of arc, I though, as I've come quite close to Newmarket in the later parts, why not actually go past there instead. So I asked Google maps for walking directions, and it gave a longer way and a shorter way. As the shorter way went past Addenbrooke's I decided to take the longer route out, and the shorter on the way back, with some embellishments at the Newmarket end.

I'm not sure what Google is playing at, but where the orange line runs, I took that, not the strange detour through Six Mile Bottom.

There's a lot of rolling terrain on that outward leg; and there was a nice grassy verge near a gate to stop and picnic. A pause in the town for a drink -- the Wetherspoon's pub was doing a Nethergate beer festival, so I had a pint of the Ruby Mild which was very easy drinking -- before looping back.

The cloud had burned off by this point, and there was a strong warm headwind for the return, before stopping to visit Karen, who was feeling improved enough after her admission on Thursday to be getting a bit stir-crazy. Then into town for Festival tickets, a much needed pint and supper, and then home.

Sunday, August 30, 2009

And you thought it was going to be easy to get full coverage of functional code... Try this little example, assuming a Haskell-like Either:

Feed it "dummy.txt" for the happy case, and something like "!!" for the bad case -- and you have an uncovered code-point for the untaken branch of the pattern -- i.e. rethrow any other exception type.

Then take that second case

from which NCover reveals we have hidden classes like <StartupCode$Tinesware-InfrastructureTests>.$Tests+ExpandFileWithJunkShouldFail@24 and <StartupCode$Tinesware-InfrastructureTests>.$Tests+ExpandFileWithJunkShouldFail@24-1 where the module is Tinesware.InfrastructureTests, the file Tests.fs and the Assert call is on line 24 of the file. And the first is 100% covered and the second is 0% covered.

The Feb 2010 CTP only generates 1 indirecting class on that line, according to Reflector, the @24 one and not the @24-1 one.

The program is out -- and this year I could barely get into high single figures for things I'd want to see. So much stuff on offer is reflex leftist narrative, anti-intellectual (but I repeat myself), implausible relationship drama, miserablist, schlock or some combination of the above. The bulk of what I'll be putting down for is from the various revival strands, the few others all foreign, including a Korean vampire movie.

They seem to have stopped doing any anime -- when I would have expected either Ponyo or Rebuild 1.x to have been on the program -- and the only animation is one claymation and a series of shorts.

Saturday, August 29, 2009

The Feb 2010 CTP (1.9.9.9) has resolved this issue. I never looked at whether 1.9.7.8 did.

This one bit me the other day. Doing the usual post-build step for the unit test assembly

Ncover.console.exe nunit-console.exe $(TargetFileName) //reg

left me with no coverage data for my F# and a lot of "Failed to load symbols" messages in the log file for the F# assemblies in nUnit's shadow copy cache.

Turns out that whereas C# assemblies have absolute paths to the .pdb baked in, F# (May CTP) has project-relative paths; so the association was being lost. Short of running the F# code through an ILDASM/ILASM cycle, the quickest fix is to turn off shadowing:

Tuesday, August 18, 2009

Listing 2.1 is an example of using wxApp.redirect() -- but that feature doesn't seem to exist in wxErlang at current; and listing 2.2 is an example of a Frame subclass that fixes size, position and title, something implicit in this and the previous listing. So we move on to putting a new control on and listening to its events.

in which I note a systematic error (now corrected) in the previous examples to do with window closing. I had been closing a window a second time in response to its Close event (raised by hitting the kiss-of-death or explicitly calling wxWindow:close(Frame,[])) in the #wx{event=#wxClose{type=close_window}} clauses; more than that, after raising the Close event explicitly, I'd not been handling it, but exiting the main loop.

As seen here, in the handler for the close event, returning the simple atom ok suffices; but after raising the close event, I need to tail-recurse back into the main loop method.

When I didn't handle a close event that I'd raised myself, when I went

then having dismissed the first window, when I launched it again, the new window was visible only fleetingly, because the close event I'd raised after close was still in the mailbox for the console. Now I do actually handle it, I can relaunch the app over and over.

Monday, August 17, 2009

These two listings are the same UI shown in C++ then Python. The wxErlang equivalent is awfully close to the miniblog example in the O'Reilly Erlang Programming book.

Still looking for an approach that doesn't end up with all the message handling logic quite so jammed together into one God-function for the message loop, and is vaguely re-usable in more than just structure.

And that ends the first chapter of fairly trivial examples. Things should get more interesting from here on in.

Sunday, August 16, 2009

It took me a while -- three months -- to realise that I hadn't seen one way or the other whether the problem with abstract internal members a couple of levels back up the inheritance tree (that thwarted my previous attempt back at the end of last year) had been fixed in the May CTP.

The cmdlet code is unchanged in the Feb 2010 (v 1.9.9.9) CTP.

Well, I can report that building

now actually succeeds. So there should be nothing stopping us writing a full PowerShell snap-in in one F# assembly.

There are a lot of books out there about learning new languages or software related technologies. The problem is that almost all of them assume that you know something about the field already; or are at least hard-core enough that you can survive being thrown in at the deep end -- the equivalent of the kids of 20-odd years ago who started out by self-teaching assembler on a BBC micro or Z80 -- and can take being started out on ODBC related code (I'm looking at you, Dive into Python.)

Hello World! is one of the rare exceptions, a gentle, and humorous introduction to the idea of programming, using Python, a language well suited to filling the niche that BASIC dialects did a generation ago. Even to a crusty and cynical old-timer, like myself, it makes entertaining reading -- not only is the writing style light and engaging, but you can nod sagely and think "Been there, done that" at all the "In the good old days" asides.

That said, it's not a book aimed at teaching people in my position, so I showed it to some members of the target demographic.

My wife, who has programmed a mean Excel spreadsheet in her time, but never anything in the way of more procedural languages, has enjoyed reading it and trying the examples (even if composing Python code using dictation software is a truly painful exercise); which is tribute to its style. While the examples may be rather trivial, in the wider sense, the immediate sense of achievement they bring help motivate and reinforce the reader.

I also showed the book to a teenager who had wanted to learn programming over the school holidays, and to whom I'd earlier loaned a copy of the O'Reilly Learning Python. She liked Hello World! very much for its very approachable style, and tells me that (to me, unsurprisingly) it gave her a better understanding of the real basics than the more advanced text has done.

However, as she also perceptively pointed out to me, "while it is very good at giving a budding programmer the groundings you'd definitely have to move on to a different book to get the more complicated bits."

It is strictly an introduction or 'taster' sort of book, a teaching aid rather than a reference. If the coding bug bites, then you will want to move onto something else to get a broader and deeper understanding, beyond the introductory simplifications (such as Hello World!'s simplifying use of old-style objects)

Looking at it as an old-timer, it is clear that the book is intended to be a whistle-stop tour of the idea of coding, and getting the computer to respond to what you have done. There isn't a sense of structured incremental development in the way material is presented, more one of getting the user to the "Ooh! Shiny!" quickly. That makes sense in terms of seeing if the coding bug bites before possibly dampening enthusiasm with comparatively boring, if worthy, things like operations on strings (split, join, search), which are left until late on. Unfortunately, one of the topics deemed too boring to mention was testing -- even though Python comes with a unit test library in the "batteries included", the idea of "how do you know if what you've written works?" wasn't raised.

The book comes with the expected accompanying download bundle : Python 2.5, and all the source and tools mentioned in the book. My wife had a little trouble with getting some of the tools to work -- the Stani's Python Editor program as supplied didn't appear when invoked from the start menu, and, when started from a command line, complained at not being able to find wxPython; although when I installed the latest wxPython for Python 2.5, the install process detected a prior version being present -- so it would help to have someone around who is confident with managing the computer being used.

Overall: definitely a good book for the absolute beginner, and I'd rate it a very solid four stars out of five. The reason I mark it down is that while it's great for teaching as it's laid out, it's less good as a reference afterwards.

Summer, the vacation season, and time when things need to get checked in to "shelf" status while the developer goes on leave, and I get a massive review and patching up of bleeding edges to do, the latest of which has been an interesting experience.

The code I was presented with is tidily written, well commented, and is what a few years ago I would have considered to be good code -- the dev who wrote it is a competent engineer, but just not close to the leading edge. So there was an apologetic note about not having been able to test a layer of the code directly above the database abstraction interface (beneath which code is all generated and subject to separate testing).

Showing how to inject a mock of the interface was easy -- but that alone would have left a mountain of unit tests to write for anything approaching good coverage. The problem was that a lot of code was repeating the same mantra

Is the record set empty? If so return an empty array
Create a new typed collection
For each record
create new typed object
initialize a type specific list of properties from fields in the record
add object to collection
Create a new typed array of sufficient size
Copy from collection to array
Return array

which is just crying out to be factored into the generic recipe as above, with the initialization line passed in as a lambda or delegate. And that factoring alone should give an order of magnitude reduction in the amount and complexity of unit tests required, which should result in a less traumatic item in the in-tray ready for the return from vacation.

Hopefully this will also be a dramatic enough object lesson in the sheer niftiness of the functional hole-in-the-middle pattern.

Rain last Thursday night was heavy enough to put the pilot light out in the back boiler!

Harvest time is upon us -- a little early even, as windfall Bramleys from next door join the plums and tomatoes; and the cut and come again salad is losing the fight against other predators.

Dead-heading the California poppies in the front yesterday late afternoon, I disturbed a frog who was hiding in the mass of vegetation. If it'd just stayed still, I'd've been none the wiser.

And I was in the garden because the front gear cable on my bike had snapped when changing up gears after getting to the top of the one noticeable hill in the area; when leaves me in bottom on the front set, and only the lowest few gears on the back block accessible without the chain catching on the front dérailleur. So, workshop fun at the weekend!

So, after a long episode of IRL (and work), and some fruitless delving through the wxErlang docs...

Now there are factorings that could be made to make this more "subclass"-able -- let loop take an arbitrary term and a fun/3 of loop, the term and a message term, passed in as a handler for any other message, and return ok if looping is to continue, and allowing for code hot-swapping; but this is probably better to just be a template at the source level.