Wednesday, December 29, 2010

2010 in media

Film

A very disappointing year, with a totally dismal Film Festival, and otherwie 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

namespace ErsharpClient

open System
open Otp
open Tinesware.Unfurling

module Main =
         
  let ConnectTo serverNode cookie =
    let clientNode = new OtpSelf("clientnode", cookie)
    let serverNode = new OtpPeer(serverNode)
    clientNode.connect(serverNode)
    
  let ReceiveRPC (connection : OtpConnection) =
    Wrapper.ToTerm <| connection.receiveRPC()
    
  let MakeRPC (connection : OtpConnection) (moduleName:string) (functionName:string) (arguments: Term seq) =
     connection.sendRPC(moduleName, functionName, arguments |> Seq.map Wrapper.ToOtpObject |> Seq.toArray)
     ReceiveRPC connection
    
  let StartGenServer (connection : OtpConnection)  =
    match MakeRPC connection "mathserver" "start_link" [] with
    | Term.Tuple [ Term.Atom "ok" ; pid ] -> pid
    | Term.Tuple [ Term.Atom "error"; Term.Tuple [ Term.Atom "already_started" ; pid2 ]] -> pid2
    | start -> raise (new System.InvalidOperationException(start.ToString()))
    
  [<EntryPoint>]
  let Main arguments =
    let connection = ConnectTo "servernode@YourNodeNameHere" "cookie"
    let pid = StartGenServer connection
    
    let args = [6I; 9I]
               |> Seq.map Term.Integer
    
    match MakeRPC connection "mathserver" "multiply" args with
    | Term.Tuple [ Term.Atom "ok" ; Term.Integer value ] -> 
      Console.WriteLine("Return Value:" + value.ToString())
    | result -> Console.WriteLine("Failure:" + result.ToString())
    
    0

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

namespace Tinesware.Unfurling

open Otp

type public Pid = { Node     : string;
                    Id       : int;
                    Serial   : int;
                    Creation : int }
             
type public Port = { Node     : string;
                     Id       : int;
                     Creation : int }
              
type public Ref = { Node     : string;
                    Creation : int;
                    Ids      : int list }             
              
type public Term =
    | Double of float
    | Integer of bigint
    | List of Term list
    | Tuple of Term list
    | Atom of string
    | Binary of byte[]
    | Pid of Pid
    | Port of Port
    | Ref of Ref

module Wrapper =
    
    let rec ToTerm (term:Erlang.Object) =
        match term with
        | :? Erlang.Atom as atom -> Term.Atom <| atom.atomValue()
        | :? Erlang.Binary as binary -> Term.Binary <| binary.binaryValue()
        | :? Erlang.Double as double -> Term.Double <| double.doubleValue()
        | :? Erlang.List as list -> 
          let contents = list.elements()
                         |> Seq.map ToTerm
                         |> Seq.toList
          Term.List contents
        | :? Erlang.Long as long -> Term.Integer <| bigint (long.longValue())
        | :? Erlang.Pid as pid -> Term.Pid {Node = pid.node(); Id = pid.id(); Serial = pid.serial(); Creation = pid.creation()}
        | :? Erlang.Port as port -> Term.Port {Node = port.node(); Id = port.id(); Creation = port.creation()}
        | :? Erlang.Ref as ref -> Term.Ref {Node = ref.node(); Creation = ref.creation(); Ids =  ref.ids() |> Array.toList }
        | :? Erlang.Tuple as tuple ->
          let contents = tuple.elements()
                         |> Seq.map ToTerm
                         |> Seq.toList
          Term.Tuple contents
          
        | _ -> raise <| new System.InvalidOperationException(term.ToString())
        
    let rec ToOtpObject (term : Term) =
      match term with
      | Term.Atom atom -> new Erlang.Atom(atom) :> Erlang.Object
      | Term.Binary binary -> new Erlang.Binary(binary) :> Erlang.Object
      | Term.Double double -> new Erlang.Double(double) :> Erlang.Object
      | Term.Integer long -> new Erlang.Long(int64 long) :> Erlang.Object
      | Term.List list -> new Erlang.List( list 
                                           |> Seq.map ToOtpObject
                                           |> Seq.toArray ) :> Erlang.Object
      | Term.Pid pid -> new Erlang.Pid(pid.Node, pid.Id, pid.Serial, pid.Creation) :> Erlang.Object
      | Term.Port port -> new Erlang.Port(port.Node, port.Id, port.Creation) :> Erlang.Object
      | Term.Ref ref -> new Erlang.Ref(ref.Node, ref.Ids |> List.toArray, ref.Creation) :> Erlang.Object
      | Term.Tuple tuple -> new Erlang.Tuple ( tuple
                                           |> Seq.map ToOtpObject
                                           |> Seq.toArray ) :> Erlang.Object

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:

%% ---------------------------------------------------------------------
%% File: mathserver.erl
%%
%% This is a simple implementation of a gen_server callback module.

-module(mathserver).

-behaviour(gen_server).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).
         
-export([
            start_link/0,
            stop/0,
            multiply/2
            ]).

-define(SERVER, ?MODULE).

-record(state, { }).
%%%===================================================================
%%% API
%%%===================================================================


%%--------------------------------------------------------------------
%% @doc Starts the server.
%%
%% @spec start_link() -> {ok, Pid}
%% where
%% Pid = pid()
%% @end
%%--------------------------------------------------------------------
start_link() ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
    
%%--------------------------------------------------------------------
%% @doc Stops the server.
%% @spec stop() -> ok
%% @end
%%--------------------------------------------------------------------
stop() ->
    gen_server:cast(?SERVER, stop).

%%--------------------------------------------------------------------
%% @doc multiplies two integers.
%% @spec multiply(X::integer(), Y::integer()) -> {ok, Product}
%% where
%% Product = integer()
%% @end
%%--------------------------------------------------------------------
multiply(X, Y) ->
    gen_server:call(?SERVER, {multiply, {X, Y}}).


%%%===================================================================
%%% gen_server callbacks
%%%===================================================================


init([]) ->
    {ok, #state{}}.

handle_call({multiply, {X, Y}}, _From, State) ->
    Reply = {ok, multiply_impl(X,Y)},
    {reply, Reply, State};
handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

%%%===================================================================
%%% API internals
%%%===================================================================

multiply_impl(First, Second) ->
    First * Second.

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

namespace ErsharpClient

open System
open Otp

module Main =

  let (|Atom|_|) text (term : Erlang.Object) =
   match term with
   | :? Erlang.Tuple as tuple ->
    let terms = tuple.elements()
    if terms.Length <> 2 then
      None
    else match terms.[0] with
         | :? Erlang.Atom as atom ->
           if atom.atomValue() = text then Some(terms.[1])
           else None
         | _ -> None
   | _ -> None
         
  let ConnectTo serverNode cookie =
    let clientNode = new OtpSelf("clientnode", cookie)
    let serverNode = new OtpPeer(serverNode)
    clientNode.connect(serverNode)
    
  let StartGenServer (connection : OtpConnection)  =
    connection.sendRPC("mathserver", "start_link", Array.empty<Otp.Erlang.Object>)
    let start = connection.receiveRPC()
    match start with
    | Atom "ok" pid -> pid
    | Atom "error" value -> 
      match value with
      | Atom "already_started" pid2 -> pid2
      | _ -> raise (new System.InvalidOperationException(start.ToString()))
    | _ -> raise (new System.InvalidOperationException(start.ToString()))
    

  [<EntryPoint>]
  let Main arguments =
    let connection = ConnectTo "servernode@YourNodeNameHere" "cookie"
    let pid = StartGenServer connection
    
    let args = [| new Otp.Erlang.Long(6L); new Otp.Erlang.Long(9L)|] :  Otp.Erlang.Object array
    connection.sendRPC("mathserver", "multiply", args);
    let result = connection.receiveRPC()
    
    match result with
    | Atom "ok" value -> Console.WriteLine("Return Value:" + value.ToString())
    | _ -> Console.WriteLine("Failure:" + result.ToString())
    
    0

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

ok_btn.Clicked += new EventHandler(OnButtonClick);

naively went to

ok_btn.Clicked.AddHandler(fun source arguments -> OnButtonClick source arguments)

but which is equivalent to, using the Event module,

ok_btn.Clicked
   |> Event.add (OnButtonClick ok_btn)

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

   // Do something only if we actually pick a file
   // Use the built-in identity function as a 'T -> 'U option mapper here
   // for the case 'T being a FileInfo option and 'U being FileInfo
   let click = handler.openButton.Clicked
                 |> Event.map (fun a -> (* 
                           open a file dialog, 
                           get a FileInfo option from the selected file name; 
                           where cancel => None *))
                 |> Event.choose id

   // Selecting an item from the menu                                       
   let select =    
       handler.openMenu.AllChildren
       |> Seq.cast<MenuItem>
       |> Seq.map (fun (i:MenuItem) -> i.Activated
                                       |> Event.map (fun a -> new FileInfo((i.Child :?> Label).Text))
                                       |> Event.filter (fun (i:FileInfo) -> i.Exists))

   // The sum of all these events                                  
   let accumulation = select
                      |> Seq.fold Event.merge click  

   // do things with a file selection event                   
   accumulation |> Event.add UpdateRecentFileList
   accumulation |> Event.add LoadFile
   ...

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?