Creating a tagged union using F# Struct with Explicit LayoutKind -
i'm trying create f# equivalent of tagged union. need in hot path of application code, discriminated unions cause of heap allocations.
here's example:
[<struct; structlayout(layoutkind.explicit)>] type result = [<defaultvalue; fieldoffset 0>] val mutable isasync : bool [<defaultvalue; fieldoffset 1>] val mutable async : async<obj> [<defaultvalue; fieldoffset 1>] val mutable sync : obj
however, problems start when want provide kind of creation methods it.
example 1
static member async(a:async<obj>) = result(isasync = true; async=a) static member sync(s:obj) = result(isasync = false; sync=s)
throws the member or object constructor 'result' takes 0 argument(s) here given 1. required signature 'result()' compilation error.
example 2
new(a:async<obj>) = { isasync = true; async = a; } new(s:obj) = { isasync = false; sync=s }
throws extraneous fields have been given values compilation error.
you have 3 problems:
- you need separate constructor arguments commas (
,
), not semicolons (;
). - object references must aligned on pointer-sized boundaries. therefore, on x64 offset object references must 8.
- static , instance member names shouldn't overlap.
this works me:
[<struct; structlayout(layoutkind.explicit)>] type result = [<defaultvalue; fieldoffset 0>] val mutable isasync : bool [<defaultvalue(false); fieldoffset 8>] val mutable async : async<obj> [<defaultvalue; fieldoffset 8>] val mutable sync : obj static member makeasync(a:async<obj>) = result(isasync = true, async=a) static member makesync(s:obj) = result(isasync = false, sync=s)
Comments
Post a Comment