Friday, 14 October 2011

Reflection - the perils

I've been struggling with Reflection. I want to create an object from a dynamically loaded assembly. In general, this is a simple problem. Just use Type.InvokeMember, easy!

However, the problem comes when the constructor does other stuff, particularly when it loads yet more objects by reflection from dynamically loaded libraries. When it doesn't work, it can be really difficult to diagnose.

The upshot of this is that it would be so much better if the constuctor did the minimum amount and all the initialisation came later, once the object had been created etc.

Just a thought.

Wednesday, 12 October 2011

Creating a class with multiple constructors in F#

Using the implicit type syntax couldn't be easier. For example:


type A (a,b) as this =
let c = "sum"
do printfn "The sum is " (a+b)


Easy! But class A only has one constructor. Suppose we want another? The obvious guess would be


type B (a,b) as this =
let c = "sum"
do printfn "The sum is " (a+b)
new (d) = B(a,0)


but this doesn't work for a number of reasons. You can't have let or do sections in your type if you have multiple constructors. So this means that a, b and c have to be defined in the new function. This means, of course, that you need to use explicit class syntax. The action can then follow the initialisation in a then clause.


type C =
val a :float
val b :int
val c :string
new (_a,_b) = { a=_a; b=_b; c="sum"} then printfn "The sum is " (a+(float b))
new (_a) = { a=_a; b=0; (* Yes, you have to initialise all the class members *) c="sum"} then printfn "The sum is " (a+(float b))


Whew! Complicated! And repetitive, potentially! It is possible to call functions in the then clause but you still have to initialise all the members in the record clause.

It's more fiddly in the presence of inheritance unfortunately. In this case the record initialiser has to include inherit Cbase(a).

Here's one I've used in production code, anonymised...


type drv = class
inherit bse

val _parser : Parser
val _columnExtractors : List

new (configuration:ExpConfig ) as x =
{inherit bse(configuration); _parser = new Parser(configuration); _columnExtractors = new List()}
then x.Init()
new (configuration:ExpConfig, parser:Parser) as this =
{inherit bse(configuration); _parser = parser; _columnExtractors = new List()}
then this.Init()

member private x.Init() =
printfn "blah blah blah"
end

Monday, 3 October 2011

F# - Abstract class

It's possible to create an abstract class, but it's not obvious how to do it. You need to create a type, as normal. Then place an abstract method declaration within. At this point, though, the compiler still grumbles. Now you have to tag the type with [<AbstractClass>].

First attempt:


> type C =
inherit Exception
new () = {inherit Exception()}
abstract print : unit -> unit
;;

type C =
-----^

stdin(14,6): error FS0365: No implementation was given for 'abstract member C.print : unit -> unit'


Now apply the annotation and, hey presto, the compiler responds with:


type C =
class
inherit Exception
new : unit -> C
abstract member print : unit -> unit
end


But why the compiler can't work it out for itself I don't know.

Overloaded constructors and inheritance - F#

I've been struggling vainly to create my own Exception class but the obvious fails to compile:


type MyException1 () =
inherit Exception ()
new (msg:string) = {inherit Exception(msg)}


with the following error message:

      new (msg:string) = {inherit Exception(msg)}
  -----------------------^^^^^^^^^^^^^^^^^^^^^^^^

stdin(9,24): error FS0762: Constructors for the type 'MyException1' must directly or indirectly call its implicit object constructor. Use a call to the implicit object constructor instead of a record expression.

After some head-scratching, I guessed that the problem might be the default constructor, and lo, this works.


type MyException =
inherit Exception
new () = {inherit Exception()}
new (msg:string) = {inherit Exception(msg)}


It's not clear to me why I need to explicitly define the default constructor, but the compiler has stopped complaining now.

Tuesday, 27 September 2011

Null coalescing operator in F#

I'm converting some C# code into F# and I was wondering where the lovely ?? operator from C# had gone. In C# we have ?? as a binary infix operator meaning

if left is null then right else left

My first crack at (re-)implementing this in F# gave me compiler headaches and so a quick trawl on the web revealed that F# interprets operators starting with (or containing, not sure at the moment) a question mark as unary operators. Aha! That would explain it. So then I defined

let inline (/??) x y = if x = null then y else x

and it seemed to work. That is, it seemed to work until I tried values slightly more complex than strings for x and y.

let y () = printfn "test" ; 2 ;;

Ho hum! Now evaluating the new operator reveals a subtlety. F# evaluates both parameters, which is unlike the if .. then .. else implementation.


"334" /?? y();;
test
val it : string = "334"


Hmmm. How should this be handled? Clearly the parameters could be wrapped in lambda functions but I'm not sure about that.... More thought required. Call back later to check.

P.S. I found another implementation, but it shares the same issue (although there are other interesting operators provided as well) unfortunately

Friday, 29 July 2011

The perils of 'ref' parameters

Arrghh! ref parameters! Don't you just love them? At least C# requires that you place the keyword ref in the calling code as well as the receiving code but even so ...

I had a nice one today. A swap object was passed as a ref parameter into a function which then called Clone_API. Now, under normal circumstances this works fine but this was a new swap and the code had been set by our code to zero. The Clone_API call did not, however, recognise the zero code and replaced it with the sicovam of the original instrument from which our working swap was cloned. Arrrghhh! Luckily our code fell over when it tried to save the instrument!

Lesson? Don't use ref parameters if at all possible and certainly not when it would be so easy to return the cloned object from the function and then explicitly reassign it in the calling code.

Thursday, 28 July 2011

Beware the yield'd iterator

In C# there are two types of iterator (as far as I know). One is an iterator into a container which is created by something akin to List<T>.GetEnumerator(). The other is the yield'd iterator and this is created by a function which yield returns each element in the sequence.

The issue is that the former can be reset but the latter cannot. Therefore, if you are using the latter you need to be very sure that it is only used the once. If a second loop through the sequence will be required then store the iterator in a list comme ca


List<T> l = new List<T>(myIterator);


and then use l instead.