2

Why do F# closures have the [<Serializable>] attribute? What would be a practical use case?

This code demonstrates serializing and deserializing a closure:

open System
open System.IO
open System.Runtime.Serialization.Formatters.Binary

let formatter = BinaryFormatter ()
let addTwo = (+) 2

(addTwo.GetType ()).GetCustomAttributes false
|> Array.iter (fun attribute -> 
    printfn "Closure has attribute: %s" (attribute.GetType ()).Name
)

let serializedClosure =
    use memStream = new MemoryStream ()
    formatter.Serialize (memStream, addTwo)
    memStream.ToArray ()

Array.length serializedClosure
|> printfn "Serialized closure length: %d bytes"

let deserializedClosure =
    use memStream = new MemoryStream (serializedClosure)
    formatter.Deserialize memStream :?> Int32 -> Int32

deserializedClosure 3
|> printfn "Invoking deserialized closure: 2 + 3 = %d"

printfn "Press any key to exit..."
Console.ReadKey true |> ignore

This works because the closure is compiled into a class (note the serializable keyword:

.class nested assembly auto ansi serializable beforefieldinit addTwo@6
    extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, int32>
{
    .method assembly specialname rtspecialname instance void .ctor () cil managed {...}
    .method public strict virtual instance int32 Invoke (int32 y) cil managed {...}
}

Since closure names (like addTwo@6) are completely compiler-dependent and change even when modifying the code only a little, I was wondering what the rationale behind making closures serializable is?

Nikon the Third
  • 2,771
  • 24
  • 35
  • it's not (yet) a closure - it's just a function ... indeed the big problems arrive as soon as start using closures within ;) - but thanks for the question - I was not aware that FSharpFunc is serializable :D – Random Dev Mar 15 '15 at 16:10
  • @CarstenKönig, well you're right. But when I compile the code in Debug mode, it definitely is a closure, because the ``2`` is not yet inlined and the class name ends in ``clo`` ;) – Nikon the Third Mar 15 '15 at 16:16

1 Answers1

1

I think the answer is that marking the class as serializable does not have any negative impact and it can be safely ignored. Not marking the class as serializable would make it impossible to serialize it (if someone found a good use for that). So, the compiler is just picking a possibly more useful default.

Is there any actual use for this? Well, if you have the same binary running on multiple machines and talking to each other using binary serialization, then you could actually pass functions around in this way. I don't think anybody actually does that (MBrace uses a more sophisticated mechanism), but it would be an option (or, it would have been an option when binary .NET serialization was cool :-)).

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553