Replies: 6 comments
-
I don't think this is a bug - page 197.
Granted, you're dealing with a private value, so interoperability is not a concern, strictly speaking. |
Beta Was this translation helpful? Give feedback.
-
To me it seems counterintuitive. Because lambda function is a value and when I store a value in a variable I would expect that the value will be reused when I reuse the variable (but instead it's recreated every time I reuse the variable). Additionally I would expect that whenever I use member _.EnsureHandlerIsField() =
let x = handler
let y = handler
LanguagePrimitives.PhysicalEquality x y |> printfn "Equal %A" prints Or that if I use field in the loop member _.EnsureHandlerIsField() =
for i = 1 to 10 do
printfn "%O" handler that it doesn't instantiate new function every time (but according to a decompiler it does). |
Beta Was this translation helpful? Give feedback.
-
under "6.9.24 Values with Underspecified Object Identity and Type Identity"
Relying on identity or lifetime of a "function value" seems to be going against the grain of the language, I assume there are many places where they get inlined (when they don't close over anything), and in other places, they allocate, and yet other places, they turn into methods. For the original case of this issue, I'm wondering if producing a warning for using function type as type argument to |
Beta Was this translation helpful? Give feedback.
-
You're right that it seems that behavior is according to spec. I found 8.6.1.3 Instance Function and Value Definitions in Primary Constructors which states
and
So the simpler fix is to somehow just ensure that right-hand side is not an anonymous function. For example following works let handler = id <| fun () ->
printfn "Updating window with new items %A" state.Items (even though Rider IDE says that let handler = fun () ->
printfn "Updating window with new items %A" state.Items
let handler = handler |
Beta Was this translation helpful? Give feedback.
-
Something like that would be nice. On the other hand I believe that let handlerX = fun () ->
printfn "Updating window with new items %A" state.Items
let handler = handlerX shall work fine. My reasoning is that I also believe that it shall work with |
Beta Was this translation helpful? Give feedback.
-
I like the stuff written, it's a pretty great idea. Brilliant! I guess when you're using weak references you are in .NET developer's mercy, the origin solution you posted smartly managed to unsubscribe handlers without the owner of handler doing anything just by the subscription manager smartly detecting if the owners are alive, getting rid of one of the task we often have to do when the owner of the handler is being disposed. You created a work around, that is not too ugly imo, if that works just use it because you are not going to do this every day tomorrow you might want to use event in F# and the day after that you might wanna check if the object is alive by manually setting a boolean value and if that's set to false you remove them from your array |
Beta Was this translation helpful? Give feedback.
-
F# compiler sometimes turns let binding with anonymous function into member function. Then when the anonymous function is needed it constructs subclass of
FSharpFunc
but this newly constructed instance is not stored so it may be garbage collected. This may affect behavior of programs which don't store another strong reference to that anonymous function.Repro steps
Here is a complete example:
Expected behavior
I would expect that function referenced by
WeakReference
created inSubscribe
isn't garbage collected and could be called.Actual behavior
F# compiler removes the only one strong reference
handler
and creates something like this decompiled code:Notice that
Subscribe
is called with(FSharpFunc<Unit, Unit>) new Program.-ctor@30(this)
which is not stored anywhere.Known workarounds
You have to wrap the callback in other type:
Related information
Beta Was this translation helpful? Give feedback.
All reactions