Supper: Porting my Comfort Zone

It was late, I was bored, this was the result… I think it’s equivalent to its C# counterpart. I’ve modified some lines for illustrative purposes and swallowed a line break here and there for brevity. A few lines at a time:

namespace Banshee.Template
open Banshee.ServiceStack
open Banshee.Sources
open Hyena
open Hyena.Data
open Mono.Addins

Nothing new here, just declaring a namespace and using some others. Dot notation is identical. I was unable to find an equivalent for C# and Java’s static import system but there appears to be a reason.

module Constants =
    let SORT = 190
    let NAME = "Banshee.Template"

No let expressions or values in a namespace so they’re wrapped in a module. Modules get compiled to classes with static values. I’m guessing this is for compatibility with other IL languages. For what it’s worth, I’ve always wondered why you can’t declare constants in a C++ namespace.

type Source() as this = 
    inherit Banshee.Sources.Source (AddinManager.CurrentLocalizer.GetString (Constants.NAME),
                                    AddinManager.CurrentLocalizer.GetString (Constants.NAME),
                                    Constants.SORT,
                                    "extension-unique-id")
    let name = Constants.NAME + ".Source"
    do 
        this.Properties.SetStringList ("Icon.Name", "multimedia-player")
        Log.DebugFormat ("Instantiating {0}", name)

This (can’t resist a pun…) is interesting, the line after do caused me some time of confusion, apparently this was not defined until the addition of the self-identifier (“as this”) before the body of the type.

The do and let statements are also of interest.

let
In C#, these would be member variables, in F# they are immutable by default but can be declared otherwise.
do
Roughly equivalent to the default constructor.

Last, we can see the familiar addition operator overloaded for string concatenation. F# also allows use of the caret, `^’ in this capacity.

type Service(name: string) as self =
    do Log.DebugFormat ("Instantiating {0}", name)
    interface IExtensionService with
        member x.Dispose () = ()
        member x.ServiceName = name
        member x.Initialize () = Log.DebugFormat ("Initializing {0}", (self :> IExtensionService).ServiceName)
    new() = new Service (Constants.NAME + ".Service")

This one’s a bit more juicy; we can see some of the power of functional programming here in the form of the name value, no need to store it anywhere. Especially useful is the enforcement of constructor chaining, since you only really have one, chaining is the only option. The language also allows specialized constructors to have specific continuations, more information here.

Casting syntax is slightly different, shown in the Initialize interface member override, I quite like this style, it’s very easy to read. It’s possibly not surprising, considering the nature of the language, interface methods must be accessed explicitly.

Notes and Other Thoughts

Order is important; inherit, let, do, interfaces, members. The syntax has a few optional elements, for example class and end markers which can, no doubt, be used for hinting when necessary. Coupled with the already terse syntax F# makes for an interesting hybrid, it feels like scripting until you make a mistake, which is when the type system steps in.

Porting something you already know is great for building momentum in a new language. After this, poking bluez via DBus becomes the next step.

Day 1: Setting Up

Summer of Code officially started on the 19th, with an exam the following day and another four days later I did not get much done this week! So, hot on the heels of Understanding Programming Languages yesterday, I decided to configure my environment ready for some development.

Pre-requisites

Gentoo is an empowering distribution, but at times can feel like a self-inflicted disability.

F# bindings for MonoDevelop will make life much easier (I do not fancy writing an fsproj file by hand!). Unfortunately the ebuild is a live one (i.e. direct from Git) and failed to compile on my system. The first hurdle appeared to be applying an assembly redirection from the requested FSharp.Core assembly version 4.3.0 to 4.3.1. Oh dear!

Luckily, the overlay system allows me to easily create my own package for the 4.3.0 assembly, working around the problem, but I still couldn’t get the bindings to compile. After many hours of fiddling, I managed to install them for my user. Not ideal, I’ll need to manage updates myself, but at least I can get started now and have some experience with the F# compiler.

Tentative Steps

With the above done, I could now create a project. BCM (Banshee Community Extensions) is mostly written in C# and provides a script for quickly creating a new extension. Using the script and existing C# template project as a starting point gets us some build infrastructure and an XML file for Mono.Addins which we can easily customize.

At this point, we note that Automake wants to use the C# compiler on our F# files! Redefining the MCS variable (among other things) works as a Quick Hack and highlights some differences between the two compilers. I’m not sure why, but although the option names are the same, F# compiler requires a second hyphen in front of each… <sigh />

A Cautious Hop

Finally, at this point there is some code to show. It’s a tiny example containing no moving parts but is useful for two reasons; first it shows an F# newcomer (me!) some of the syntax for polymorphism and secondly, combined with the prior ground work gets us to the point where we can see an effect on the outside world, i.e. the extension can be loaded by Banshee and we see an (at present) icon-less source appear when it is enabled.

namespace Banshee.Template

type Source() = 
    inherit Banshee.Sources.Source ()

type Service() =
    interface Banshee.ServiceStack.IExtensionService with
        member this.Dispose () = ()
        member this.get_ServiceName () = "TemplateService"
        member this.Initialize () = printfn "Starting TemplateService"

Next Up

The most logical next step would be to tidy up the changes I’ve made to enable F# projects to build, figuring out what changes are needed to get this done via GNU Autotools is definitely a priority. Porting the rest of the C# template extension to F# is also an ideal candidate for attention due to the valuable language experience that I would gain. Once done it would be useful to expand the extension creation script for other users, though that has a low priority. Finally, today’s work provides an excellent place to start prototyping.

A slow day, not many achievements but each one felt significant.