Sunday, February 06, 2011

Getting the baked-in .pdb location from an assembly with Mono.Cecil 0.9.4

Because it isn't always as simple as

as is done in Mono.Cecil.Pdb.PdbHelper, if assemblies and symbols have been moved to separate locations during a build.

The tools are there -- we just need to get the debug data from the PE image if it's present, skip the first 24 bytes, and interpret the rest as a string. Alas, all the are annoyingly just slightly encapsulated from us. But never mind! Reflection gets us there without having to negotiate a patch or make a fork:

Wednesday, January 19, 2011

Monad.Zero -- doing it right

For my own benefit (see title of blog) as much as anything else. When I wrote

Rule 1 of monadic parsers is -- if you return Monad.Zero, you're probably doing it wrong... It's likely that you mean monadic return of an empty list.

it's because there's a distinction between positively returning an empty result (i.e. successfully doing nothing) and returning nothing at all (not succeeding in what you were trying to do) -- as the F# documentation for Zero puts it

Called for empty else branches of if...then expressions in computation expressions.

So, for a parser monad Zero is the function that returns a parser that takes no input and always fails:

for the Enumerable or Seq monad, it's the empty sequence, for Maybe its None and so forth -- basically the only thing you can return if you don't have any value to return.

And for individual leaf parsers -- the functions that define an Operation<TInput, TOutput> and return them wrapped as a Parser<TInput, TOutput>, those Operation<TInput, TOutput>s should return the same non-value when faced with a parse failure.

By contrast, when composing a parser that may try to consume some of the input, but fail, and you want to not fail the whole parse, you need a parser that successfully matches nothing (and consumes nothing) as an alternative that provides a success value -- and that is not Zero, but rather Return of the non-value of the appropriate type. So, for example, the parser combinator Many:

is "Consume as many blocks of p as you can -- or, if that fails, do nothing"; by contrast, the combinator Sat fails if the predicate doesn't match:

So in that case it says Zero and means Zero because that's a failure to satisfy the parser -- here in the equivalent the F# computation expression we don't even have to write the else branch; it's filled in for us by the compiler.

And that's really the one subtlety to be borne in mind -- otherwise you end up with an almost intractable debugging issue when your parser fails unexpectedly, partway through consuming valid input.

Tuesday, January 18, 2011

Monadic Parsers in C#

Updated 17-Jan -- because I realised I'd gotten Input and Output the wrong way around; too easy to do when you're using the same type in each case.

Updated 18-Jan -- In which we bug-fix the heck out of the previous two iterations, and pretty much completely rewrite this post. Rule 1 of monadic parsers is -- if you return Monad.Zero, you're probably doing it wrong... It's likely that you mean monadic return of an empty list.

Following on from Mike Hadlow's recent series of posts on monads in C#, and the "Aha!" moment that SelectMany actually means Bind, in the same way that Select means map, I thought I'd take it for a spin on something more than just the usual Identity, Maybe and State monads.

For a long while now there have been things like illustrative F# ports of a Haskell monadic parser -- so why not, I thought, try to emulate that in C#?

So we have a type which looks like this (abusing KeyValuePair as a 2-tuple for .net 3.5 compatibility) --

which is a monad upon the return type; the input stream parametrization being orthogonal to this.

The monad itself (and here I've reverted to using Bind for the simple case analogous to the F# case) looks like

Here ToParser is the convenience function-to-monad constructor; and Return is what lifts an output value into the monad -- creating a parser that places that output value into the output stream.

The combinators assemble all the parsers from the atomic units -- some here are more specialized than others.

And we can top this off with an example

which produces a successfully parsed output

key=[3; 5; 5; 3]; value=[]
key=[35]; value=[]

So what lessons do I draw from this exercise?

The big one is that old saying about needing to be twice as clever to debug code as to write it; and code that works with continuation passing can get pretty darn clever. Or, as Eric Lippert put it (in the context of writing asynchronous code in this style in C#):

Remember what I was saying about the pros and cons of CPS?

  • PRO: Arbitrarily complex and interesting control flows can be built out of simple parts – check.
  • CON: The reification of control flow via continuations is hard to read and hard to reason about – check.
  • CON: The code that represents the mechanisms of control flow completely overwhelms the meaning of the code – check.
  • CON: The transformation of ordinary code control flow into CPS is the kind of thing that compilers are good at, and almost no one else is – check.

The parts are indeed individually simple enough; but all the rest is sadly true. We can see how clever, what the actual power-to-weight ratio is, or how much what actually gets executed differs from what it superficially looks like we've written, by replacing the initialization in ToParser with

for a static integer value max in the class. Running the test example, we see that the stack depths achieved by these simple parsers are 64 and 95 respectively -- causes and effects are remote from one another (with the side effect that the only code not covered in this belongs to the subtract and divide operator parsers, and the failure handlers in the main program.

Coupled with this is the difficulty of doing anything meaningful in the way of fine-grained TDD in the bootstrap phase -- the individual pieces are not parsers, are comparatively trivial, and even those return functions operating on functions; it's in combination that they do their magic, and there's a lot of code needed just to read one token out of a stream.

Having the F# equivalent to work with -- to provide guidance of what types all the individual pieces were, and then in essence manually de-sugaring the computation expression notation -- was invaluable. But if you have the F# version, there is little need for the transposition except as a five-finger exercise like this.

On the positive side, though, once you have the toolkit like this and it handles even the simple cases, that probably means that it is robust; and then it can pretty much be taken as a black box, for those times when you absolutely have to do it in C# rather than F#.

Sunday, January 16, 2011

More Garden Rubbish

Insanely mild weather today meant that when I slipped out in bare feet and T-shirt to check the greenhouse, I ended up doing a bit more pottering around in the garden to catch up with some of the tidying from the autumn tasks without feeling the need to wear more.

I did put on a shirt and sandals for the catch-up pruning of the apple trees and digging over the beds where the annual flowers and the broccoli, which didn't survive the harsh weather in Nov-Dec, had been.

Tuesday, January 11, 2011

Using F# 2.0 Powerpack ArgParser from C# -- (ii)

Having resolved the issue of why the "--" separator wasn't triggering (PowerShell was swallowing it before it got to my code) that was stumping me in the previous post, I put together a little fluent wrapper to make this a little easier to consume from C#. The code that isolates the F# types looks like this:

The calling code, for the same example as before looks like

which is much clearer.

Now edited for FxCop.

Monday, January 10, 2011

Garden Rubbish and Meaningless Numbers

You can tell quite how early -- late November -- the big freeze set in, as for the last couple of weekends I was doing things like raking leaves off the lawn, as well as other winter chores like pruning roses and clearing other dead foliage from expected dieback (enough to fill the green bin). The cold was also enough that inside the greenhouse, even under a further bubble-wrap tent with a heater set to frost-free, some of the pelargoniums got scorched -- not something I've had happen before in a winterised greenhouse.

In the weekend clearout, I got rid of the last tomato plants from the tent, harvesting one last tomato. Sunday I baked a crumble and almost used up the last of the apples -- leaving two Charles Ross picked and packed remained in a box of fruit that had mostly spontaneously self-destructed; and a large windfall Bramley (we ate the former raw and baked the latter for dessert today). Many of the picked-as-ripe Bramleys also self-destructed from within in the last couple of weeks; the windfalls were just as durable as the cosseted ones.

And some numbers -- at 08:39-08:40 on 21-Oct-10, the digital clock and odometer coincided; as again, cheating at 09:50 BST on 2-Nov; not cheating at 17:43-40 on 6-Jan-11; 1000 miles on 4-Nov. The bike read 1033.9 miles at the end of the year (and also on the 6 month mark of having the bike computer, 7-Jan).

Using F# 2.0 Powerpack ArgParser from C#

This is an update of the technique mentioned in an antique post by Robert Pickering which was referenced by Laurent Le Brun last summer. I've taken Laurent's example of F# usage and ported it to C# in the most direct fashion:

It is possible to streamline this to hide most of the messy type names inside utilities.

One thing I've not managed to do is get the lambda associated with the ArgType.Rest to fire, even after setting the default handler opt1 to FSharpOption<T>.None. That -- the default handler -- gets fired every time an otherwise unmatched argument is encountered; the ArgType.Rest handler looks from the code like it should "just work" so I'm a bit baffled ATM.

LATER: Mystery solved

Of course, I was testing this at a PowerShell prompt -- and the shell was swallowing the unquoted "--" string : there was no "rest" to operate on.

Wednesday, December 29, 2010

2010 in media

Film

A very disappointing year, with a totally dismal Film Festival, and otherwise only the Chaumet/Tati L'Illusioniste really standing out enough to tempt me to the cinema. I would have gone to see The Story of Kells as part of the festival had it not been in a no-unaccompanied-adult showing; but wasn't motivated to see it when it came around later. And similarly, previous commitments and bad weather relieved me of having to decide whether to make the effort to fit in Rare Exports.

Books

I actually read a few this year that weren't software related. Excluding the holiday reading potboilers (Lindsey Davis' latest Falco, some by the numbers sci-fi,...)

  • Miéville's Un Lun Dun was a young people's Neverwhere -- some nice ideas, but it didn't quite cohere in the end. And I'm sufficiently bourgeois that the mundane London in the book was a more alien world than Un Lun Dun itself.
  • Also by Miéville, The City and the City is the first Hugo winner I've read before the award since A Fire Upon The Deep. An interesting conceit of cities wrapped around a police procedural.
  • Reynold's Terminal World was a vast improvement over his previous House of Suns, being a fairly straightforward adventure yarn in a setting where Vingean Zones of Thought happen on a scale of miles rather than kiloparsecs.
  • I also finally got around to Nahoko Uehashi's Moribito: Guardian of the Spirit -- and was surprised quite how much the anime had expanded upon the rather short and sparse narrative.

And while I'm here, probably worth warning people about the two weakest of the computing texts I picked up this year, both in the Wrox Professional series:

  • Professional Iron Python was a very strange book, and it did cover some obscure points of .net/Windows programming; but for IronPython, not good. It read like a draft that had been put together while the language was still in its pre-beta stages and then hurriedly given a Visual Studio 2010/.net 4 gloss. In particular the author repeatedly makes the incorrect assertion that IronPython statements cannot span multiple lines -- which leaves me dubious as to the rest of the content I've not independently verified. Get IronPython in Action instead.
  • Professional F#2.0 just approaches being content free. It covers very little of the language (no computation expressions, let alone anything like quotations), giving more emphasis to the imperative rather than functional aspects where it does. Get the O'Reilly Programming F# instead.

Anime

2010 was the year where Crunchyroll reached a sufficient point that -- whatever the sordid history of the operation might be -- it was possible to watch a fair selection of series without resorting to fansubs. A few series that I might have watched, or at least sampled (House of Five Leaves, Tatami Galaxy) were streamed by Funimation -- but they don't seem to have cottoned on that the world is more than just Japan and the US.

Going by the metric that "/a/ doesn't talk about good anime" -- where it is obvious whether a title that is not talked about is good or bad -- House of Five Leaves, from a manga by the same author as Ristorante Paradiso is the only one that I feel any regrets about missing.

Apart from titles already blogged, I still have the last episode of Virgin Pomegranate Monster to watch, as well as the concluding cours for Letter Bee REVERSE and Super Robot Wars OG : The Inspector.

And of course no discussion of 2010 in anime would be complete without a mention of the new GAINAX series, Panty & Stocking with Garterbelt, a title that I watched just enough of to feel I could add it to my MAL dropped list (i.e. more than one episode).

A combination of all that is wrong with American cartoons multiplied by "LOL, Japan!", this was the disappointing result of giving a studio of talented animators full freedom to have fun and do what they wanted. Alas, what they wanted to do was act like retarded 12-year-olds -- so if you've grown out of finding messy bodily functions funny, or haven't seen any of the stuff that they're lampooning, and don't get your jollies from hearing cute Japanese girls swearing a blue streak, it ends up by being the saddest waste of talent I've seen in many a year. And another case where I ignored the implication "it's being talked about, ergo it isn't very good", because I couldn't believe it was really that bad.

Alas, it was. In fact, watching the audience reactions as they were trolled mightily at every turn with misleading hints about forthcoming episodes, and desperately tried to make it all make sense, all the way up to the sudden ending with "To be continued in next season" (when Gainax have never done a second season of any of their original anime) was far, far more entertaining than the series itself.

Tuesday, December 28, 2010

“Hello, OTP!” from F# revisited

That previous F# code was just too ugly to leave as it was; so after a little bit of work, I've factored out a general purpose wrapper to convert the Otp.Erlang types into values of a discriminated union on the F# side of the fence. Like this we can directly pattern match, without the descent into massive nesting that we had before, and keep the Otp.Erlang types encapsulated into wrappers for method calls on the Otp types.

With this addition the main program above can be revised to become

which looks a lot more like the language we're trying to write in. All the magic happens in this file

Of course, as OTP.Net is some revs behind the current Erlang distro's JInterface, this type mapping is incomplete (no BitStr or Fun types) compared with what we could be using. The main advantage is that it works right now.

“Hello, OTP!” from F#

Nothing earth-shattering here, just recording the results of a little bit of playing around with OTP.Net and F#. This is all building on the original work done elsewhere Integrating .NET and Erlang using OTP.NET and Integrating F# and Erlang Using OTP.NET, as a little bit of a five-finger exercise using the OTP framework as now explained in Erlang and OTP in Action.

So, simple gen_server to export the same sort of API as the mathserver example in the former:

Compile this using erlc and start werl -sname servernode -setcookie cookie. Meanwhile the matching F# program to build and run is

Matching the dynamic types possible with Erlang, and the F# way with type hierarchies, makes this code somewhat ugly (as in multiply nested decision points and the start of the arrow anti-pattern) when trying to unpick the return values, especially trying to decode the possible return values when requesting that the far end server start up.

Some of the repeated noise has been factored out into the Atom active pattern for dealing with {Reason, Payload}, but the underlying data model in OTP.Net is simply not very F# friendly.

Anime — Giant Killing

When this title was announced for the spring season, my reaction was "Oh, football..." and pass it by -- but towards the end of its airing, it had become one of those series that hardly ever got talked about, but always positively when it was mentioned. So, with a fairly thin line-up for autumn, I went back and gave the first episode a try...

And it has turned out to be my pick for the best series of the year, by being so much not what the bulk of anime has become in recent years : the characters are adults, there's no romance, or borderline smut, or cute girls doing things cutely. It also confirms the trend that series where the characters have perceptible noses are ones worth investigating.

The story opens when East Tokyo United, a team in a prolonged slump, bring back a former star player, Takeshi Tatsumi, from England, where he as been coaching amateur (or at least not full-time professional) sides to good effect -- like taking them to the 4th round of the FA Cup. This return as coach after having abandoned the team years before rankles amongst some of the players and many of the fans; the more so when he finally shows up at training, and chooses a starting side mainly from the reserves.

Slowly, with a mixture of shrewd insight, and complete irreverence to the way things are done on and off the pitch (like sloping out of a press conference for an informal chat with the manager of the national team), Tatsumi starts to bring the team together. At last ETU notches up a few wins, and then in the climax of the series, have to face the Osaka Gunners, who in their previous match steamrollered a stronger side than ETU 8-0, in a match that actually spreads over more than 90 minutes of air time.

The manga continues; we have only come half-way through the new season, and there isn't a plot-wrapped-up end. If there were to be a second season, I'd watch it.


Saturday, December 25, 2010

Links for 25-Dec Bumper catch-up edition

2010 having spanned the run from first integration point through to RTM and GA for XenDesktop 5, I was being increasingly preoccupied as the year went on; and blogging of any form was one of the main casualties. Which means I have a not-so-little list of backlog of things I want to keep track of from the last couple of months:

F#

.net General

Build Process

Misc.

F# GUI plumbing with reactive Events

My most recent "Aha!" moment with the language is to finally wrap my head around the standard Event module -- a sort of lightweight subset of the Reactive Extensions for .net -- while starting to do some more GUI programming in F#, which is making belated use of the GTK#/Glade spikes I made about a year ago.

It may not make much difference in the simplest cases where

naively went to

but which is equivalent to, using the Event module,

At this point the main difference is the change in the function signature -- first, it is a real F# function rather than being forced to use the implicit cast from a fun to a delegate, even if the function signatures look compatible on the surface; second the function passed to Event.add doesn't have the source argument (but, as shown, that can be brought in as a closure).

So that's a small win from the beginning -- but that just scratches the surface. Where it actually shines is where multiple sources of events have to be handled in much the same way. For example, given a menu containing recently accessed files, with selection meaning to re-open that file, as if they had been selected from a file open action

All the inhomogeneity of the event sources (button click, menu item activation) and their associated EventArgs types is smoothed away by appropriate Event.map calls and the use of closures; different validations are handled by appropriate Event.filter or Event.choose invocations; and then the whole ensemble is gathered together by an appropriate fold with Event.merge as the accumulator.

True, there is nothing here that could not be achieved by making old-style handler functions for AddHandler from equivalent appropriately composed function chains -- the path I was starting to take for this bit of plumbing before I was indirectly reminded of this feature, and dug up this series of posts from a couple of years back (so slightly dated in the details). The big difference that using the Event module makes is that it is more expressive of intent, and separates the concerns -- general event handling plumbing vs this application's business logic -- explicitly.

A white-ish Christmas

Last Saturday started dry but cold, though with some ice still on the road outside -- cycling into town in multiple layers, with only my nose exposed, that was very cold for the first couple of miles until I started to radiate enough heat through it. I got back home mid-afternoon, and took a nap, waking to find the world turned white.

So it was a work-from-home start of the week, while waiting for the ungritted roads in the village to be pounded clear; with a brisk yomp to Waitrose to get me out of the house. By Thursday, as the threatened midweek snow had come to nothing, I did go into the office (probably getting a lot less done than had I stayed at home).

Yesterday, I did the approximately biennial feat of cycling into work for the shortest working day -- although the fields were white, and the sky grey, the road was dry, and the weather, although still below zero on the way in, was milder than it had been (showing quite how accustomed we soon become to the cold). And in doing so that put me over the 1000 miles for this half year.

Today is brighter and sunny, but colder. Where I cleared the drive is dry, but the untouched snow is showing no signs of turning to slush like it had a few days ago. I shall have to make my way down the garden to check the greenhouse and the broccoli.

Tuesday, December 07, 2010

Winter Wonderland

The car thermometer showed -6 as I started out to work at about 08:45 this morning, dropping quickly to -8, and then slowly recovering to -7. Isn't it time we had an apology for predictions like this one from ten years ago?