Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Null-checking considerations in F# – it's harder than you think (latkin.org)
26 points by latkin on May 18, 2015 | hide | past | favorite | 7 comments


It sounds like this boils down to a codegen problem/bug with == / <>, mm? I recall a similar problem doing comparisons on some value types, perhaps it was DateTime (IIRC, this was before VS2010). The fix was to add another case to the operator to make it take the fast path (do a direct call to the compare method vs some crazy generic path). Rather than make the code more verbose to hack around compiler limitations, fix the compiler? Though:

  if x == null then ... else ...
is about the same as:

  match x with null -> ... | _ -> ...
That said, null checking was never a perf area nor anything I've really had to deal much with in years of working with F#.


The "crazy generic path" is still the default, but in F# 4.0 now there is a module `NonStructuralComparison` which can be opened, shadowing all of the generic operators with fast non-generic guys. See [this](http://blogs.msdn.com/b/dotnet/archive/2015/04/29/rounding-o...) blog, search for "non-structural comparison operators".


When I get to a PC I'll try it out. But basically instead of using IComparable directly (so you'd just have a single function call), it used to do something far more complicated first, but still end up calling the same compare function.

For equality I'd expect it to inline a check for null before calling the full equality check. Then a later optimization pass or the JIT could fix it up to be just the null check.


Is there some .NET platform / interop issue that requires F# to have null references? SML and OCaml have Option types and Haskell has the Maybe Monad. It seems weird that F#, being an ML-family language, requires checking for references to null.


Idiomatic F# code also uses Option types. However, all .NET reference types have null as a possible value. While most F# types don't have null as a "normal" value, there's nothing to prevent null instances of these types from being created "abnormally" at the .NET runtime layer (e.g. values of F# types created in other .NET languages like C# that don't respect F#'s metadata annotations, or created via F# operators like Unchecked.defaultof<_> that implicitly use the .NET runtime's default value of null for reference types).

In practice this is rarely a problem, but the article is highlighting what you need to do when you want to (efficiently) check for these boundary cases.


This is really good stuff, but most importantly remember that every time you go out to .NET and could get a null, sort it all out as close to the call as possible. Don't be cute and wrap it in an option, or try some 3-levels-out try-catch block from hell. Acknowledge what could happen and deal with it.

I've found that every little bit my code gets away from that call without handling the null, things get more and more complicated.


> Don't be cute and wrap it in an option

Unless of course that's the right semantics. Often methods use nullable references as a poor man's Option.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: