Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# records vs .net struct

Tags:

.net

f#

is f# records is the same as .net struct? I saw people talk about f# struct,are they use this term interchangable with F# records? Like in FSharp runs my algorithm slower than Python, talking about using struct as dictionary key but with code type Tup = {x: int; y: int} Why is this faster than a tuple as a dictionary key in the link above?

like image 585
user8321 Avatar asked May 02 '11 14:05

user8321


3 Answers

To answer the second part of the question, it's really about using them as a dictionary key.

The speed of using something as a dictionary key comes down to how the GetHashCode function works for that type. For reference types such as Records, the default .Net behaviour uses Object.GetHashCode which "computes the hash code based on the object's reference" which is an efficient numeric operation.

The more complex default behaviour for value types, which is what structs are is ValueType.GetHashCode "method of the base class uses reflection to compute the hash code based on the values of the type's fields." so the more complex the struct and depending on its fields, computing the hash could take a lot longer.

like image 99
Andy Dent Avatar answered Oct 24 '22 04:10

Andy Dent


No, in fact, a record type in F# is a reference type just with special functional programming features like pattern matching on properties, easier immutability, and better type inference.

I think Laurent's speedup must have been for other reasons, because we can prove that Tup is not a ValueType:

type Tup = {x: int; y: int}
typeof<Tup>.BaseType = typeof<System.Object> //true

Whereas

type StructType = struct end
typeof<StructType>.BaseType = typeof<System.ValueType> //true
typeof<StructType>.BaseType = typeof<System.Object> //false
like image 38
Stephen Swensen Avatar answered Oct 24 '22 06:10

Stephen Swensen


As Stephen said, it is a reference type. Here is the compiled code(release mode) of type Tup = {x: int; y: int}:

[Serializable, CompilationMapping(SourceConstructFlags.RecordType)]
public sealed class Tup : IEquatable<xxx.Tup>, IStructuralEquatable, IComparable<xxx.Tup>, IComparable, IStructuralComparable
{
    // Fields
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    internal int x@;
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    internal int y@;

    // Methods
    public Tup(int x, int y);
    ...

    // Properties
    [CompilationMapping(SourceConstructFlags.Field, 0)]
    public int x { get; }
    [CompilationMapping(SourceConstructFlags.Field, 1)]
    public int y { get; }
}
like image 4
Yin Zhu Avatar answered Oct 24 '22 05:10

Yin Zhu