Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling Null Values in F#

Tags:

c#

null

interop

f#

I need to interop with some C# code with F#. Null is a possible value that it is given so I need to check if the value was null. The docs suggest using pattern matching as such:

match value with | null -> ... | _ -> ... 

The problem I'm having is the original code is structured in C# as:

if ( value != null ) {     ... } 

How do I do the equivalent in F#? Is there a no-op for pattern matching? Is there a way to check for null with an if statement?

like image 764
Jonathan Sternberg Avatar asked Jul 25 '11 14:07

Jonathan Sternberg


People also ask

How do you handle null values?

Putting the median or mean of the whole column was the simple approach. But I like a bit more specific approach to the median and mean. Instead of taking the median of the whole age column and filling up all the null values, filling up the null values using the mean age of each pclass and 'alive' will be more accurate.

Does F# have null?

The null value is not normally used in F# for values or variables. However, null appears as an abnormal value in certain situations. If a type is defined in F#, null is not permitted as a regular value unless the AllowNullLiteral attribute is applied to the type.

How do you handle null in JavaScript?

Javascript null is a primitive type that has one value null. JavaScript uses the null value to represent a missing object. Use the strict equality operator ( === ) to check if a value is null . The typeof null returns 'object' , which is historical bug in JavaScript that may never be fixed.


2 Answers

For some reason (I haven't yet investigated why) not (obj.ReferenceEquals(value, null)) performs much better than value <> null. I write a lot of F# code that is used from C#, so I keep an "interop" module around to ease dealing with null. Also, if you'd rather have your "normal" case first when pattern matching, you can use an active pattern:

let (|NotNull|_|) value =    if obj.ReferenceEquals(value, null) then None    else Some()  match value with | NotNull ->   //do something with value | _ -> nullArg "value" 

If you want a simple if statement, this works too:

let inline notNull value = not (obj.ReferenceEquals(value, null))  if notNull value then   //do something with value 

UPDATE

Here are some benchmarks and additional information on the performance discrepancy:

let inline isNull value = (value = null) let inline isNullFast value = obj.ReferenceEquals(value, null) let items = List.init 10000000 (fun _ -> null:obj) let test f = items |> Seq.forall f |> printfn "%b"  #time "on" test isNull     //Real: 00:00:01.512, CPU: 00:00:01.513, GC gen0: 0, gen1: 0, gen2: 0 test isNullFast //Real: 00:00:00.195, CPU: 00:00:00.202, GC gen0: 0, gen1: 0, gen2: 0 

A speed-up of 775% -- not too bad. After looking at the code in .NET Reflector: ReferenceEquals is a native/unmanaged function. The = operator calls HashCompare.GenericEqualityIntrinsic<'T>, ultimately ending up at the internal function GenericEqualityObj. In Reflector, this beauty decompiles to 122 lines of C#. Obviously, equality is a complicated issue. For null-checking a simple reference comparison is enough, so you can avoid the cost of subtler equality semantics.

UPDATE 2

Pattern matching also avoids the overhead of the equality operator. The following function performs similarly to ReferenceEquals, but only works with types defined outside F# or decorated with [<AllowNullLiteral>].

let inline isNullMatch value = match value with null -> true | _ -> false  test isNullMatch //Real: 00:00:00.205, CPU: 00:00:00.202, GC gen0: 0, gen1: 0, gen2: 0 

UPDATE 3

As noted in Maslow's comment, an isNull operator was added in F# 4.0. It's defined the same as isNullMatch above, and therefore performs optimally.

like image 171
Daniel Avatar answered Sep 18 '22 14:09

Daniel


If you don't want to do anything in the null case, then you can use the unit value ():

match value with | null -> () | _ -> // your code here 

Of course, you could also do the null check just like in C#, which is probably clearer in this case:

if value <> null then     // your code here 
like image 44
kvb Avatar answered Sep 22 '22 14:09

kvb