The active pattern in this question fails to compile after upgrading to VS 2012 RTM. It provides a way to do a type test and match a literal within a single pattern. For example:
let (|Value|_|) value =
match box value with
| :? 'T as x -> Some x
| _ -> None
let getValue (name: string) (r: IDataReader) =
match r.[name] with
| null | :? DBNull | Value "" -> Unchecked.defaultof<_>
| v -> unbox v
Can this be done without the active pattern? I realize a when
guard could be used (:? string as s when s = ""
) but it can't be combined with other patterns.
kvb's variation (which doesn't do quite the same thing since it assumes the type test succeeds) can be modified to produce a similar pattern:
However, there is a subtle performance difference. The original active pattern translates to:
that is, it does a type test and cast. It's usage (
match x with Value "" -> ...
) translates to:Most notably, the typed value returned from the pattern is matched using the typical compiler transformations for patterns (
string.Equals
for strings).The updated pattern translates to:
which uses generic equality and is less efficient than matching against a literal. The usage is a bit simpler since equality is baked into the pattern:
Anyway, it works. But I like the original better.