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.

Monday, 27 June 2011

newCSRTransaction - returns null on error ... or does it?

Well, the documentation states that CSMTransaction.newCSRTransaction returns null if the function fails, ie if the transaction sought is invalid. Perhaps this is true in some cases but it certainly isn't true all the time, as we have observed.

Mysteriously our code was failing and a MNoSuchDealException was being thrown. Where was it coming from? Guess what? It came from CSMTransaction.newCSRTransaction! So those null checks we had were pretty useless in this instance, although I suppose they might be necessary, there's no real way of telling until a null is returned (like the docs state should be the case).

Ho hum, so now we have another wrapper:


public static OptionType<CSMTransaction> NewCSRTransaction(int transactionId, short version)
{
try
{
return CSMTransaction.newCSRTransaction(transactionId, version);
}
catch (MNoSuchDealException)
{
return OptionType<CSMTransaction>.Null;
}
}

Friday, 20 May 2011

Checking for null in generic methods

My OptionType<T> class indicates whether the underlying reference type is null or not whilst retaining all the good type information and forcing the hand of the developer to think about checking for null, at the very least (unfortunately the C# compiler won't let me force the check :-( ). But this didn't work very well for string types because string.Empty is also considered as a null value in many circles, including this one, hence the prevalence of string.IsNullOrEmpty checks all over our codebase.

Now the problem arose when I had an OptionType<string> which was used to represent string.Empty. The simple check I had in place was nothing more than an equality check with null which was clearly unsatisfactory here. What I needed was to check using string.IsNullOrEmpty, but only when T is a string.

The obvious way to approach this would be to abstract out the null checking behaviour, not into a separate parameter because that would be nasty but into a set of functions from which the compiler would make the appropriate selection. Mind you, non-generic calling code worked just fine! Typical!

And so I introduced


public static class Check
{
public static bool IsNull(string s)
{
return string.IsNullOrEmpty(s);
}

public static bool IsNotNull(string s)
{
return !IsNull(s);
}

public static bool IsNull(T t) where T : class
{
return t == null;
}

public static bool IsNotNull(T t) where T : class
{
return !IsNull(t);
}
}


To my dismay, however, the call to Check always selected the generic method, even when the generic type was actually a string. Argh! And so we end up with


public static class Check
{
public static bool IsNull(string s)
{
return string.IsNullOrEmpty(s);
}

public static bool IsNotNull(string s)
{
return !IsNull(s);
}

public static bool IsNull(T t) where T : class
{
return t == null;
}

public static bool IsNotNull(T t) where T : class
{
return !IsNull(t);
}

// We need these two because OptionType cannot call IsNull(string), it can only call IsNull(string)
public static bool IsNullString(string s)
{
return IsNull(s);
}
public static bool IsNotNullString(string s)
{
return IsNotNull(s);
}
}


which is called from the OptionType constructor in the following manner:


if ((typeof(T) == typeof(string) && Check.IsNotNullString(t as string)) || (typeof(T) != typeof(string) && Check.IsNotNull(t)))
{
_t = t;
_isEmpty = false;
}


Not pretty, but it does work. Let me know if you come up with a neater way to achieve this.

Wednesday, 18 May 2011

Null values in dictionaries

Eeek! Why on Earth would someone insert null values into a dictionary? Especially when one sees code like


Dictionary<A,B> d = new Dictionary<A,B>();


blah


TryGetValue( key, out value);
if(value==null) throw new Exception();


That is to say that the return value from TryGetValue is routinely ignored and instead the null-ness of the output value is used to indicate failure. Clearly this has been written because the original author didn't want to wrap dictionary access in try ... catch(), which is understandable, but ...

So I propose that null indicates failure. With this in mind, we can rewrite TryGetValue as follows:


public static Nullable<V> TryGetValue(Dictionary<K,V> d, K key)
{
V v;
bool s = d.TryGetValue(key, out v);
return s ? v : (Nullable<V>)null;
}


This is, of course, absolutely spiffing because now TryGetValue is a function which returns the sought value and so lends itself to a declarative programming style.

Also, with the parameters in the order key then dictionary we allow ourselves the possibility of function pipelining.

Monday, 9 May 2011

Overriding the database access in CSMApi

Sophis' CSMApi class provides the method GetDBAccess(CMString). At first blush this is not going to help because the CMString is passed in and not out of the method. However, the CMString is a tricky class, and it has the method SetString() which allows you to change the underlying string representation even if the object itself has all the appearances of being constant, or at least non-modifiable. Another good reason to avoid CMString.

Anyway, the upshot is that you can override GetDBAccess to provide your own connection details. Interestingly, it turns out that if your CSMApi derivative is in the exe this all works fine but if it is in a dll then, oh dear, it doesn't work. I don't know why at this point, but I assume that there are statics in CSMApi which have some evil order-dependencies...

I'll let you know if I find out what's going on.