Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# handling values and references

Tags:

.net

reference

f#

I need to understand something very important regarding F#: how it handles references and values. I know that F# defines immutable and mutable objects and also know the reason why.

But there is one thing that I do not know: how are objects treated?

I mean, in C# everything is a pointer and when assigning to an object the reference of another one, data are the same, and we'll have two pointers pointing the same data.

So in C# if I have this:

Object myobj1 = new Object();
Object myobj2 = myobj1;
bool myobj1 == myobj2; // It is true

Well, what about f#?

let myvar: MyObj = new MyObj ()
let myvar2: MyObj = myvar

What's the situation here? Does the assignment involves copy? or not.

And, generally speaking, what's f# approach to this topic? (I mean value vs reference).

like image 674
Andry Avatar asked Dec 07 '22 23:12

Andry


1 Answers

When working with reference types and value types, F# behaves just like C#.

  • When you have a reference type, it works with a reference to an instance in the heap.
  • When you have a value type (built-in, declared in C# or declared in F# using Struct attribute),
    the value is copied when you assign it to another value or pass as argument.

The only notable difference is that standard F# types (discriminated unions, records, lists, arrays and tuples) have structural equality semantics. This means that they are compared by comparing the actual value stored in them and not by comparing references (even if they are reference types). For example, if you create two lists of tuples containing the same data you get:

> let l1 = [ ("Hello", 0); ("Hi", 1) ]
  let l2 = [ ("Hi", 1); ("Hello", 0) ] |> List.rev;;
(...)

> l1 = l2;;
val it : bool = true

You get true even though lists and tuples are reference types. If you compare the references however (EDIT: Added sample inspired by kvb):

> System.Object.ReferenceEquals(l1, l2);;
val it : bool = false

The use of structural equality makes sense in F# because the types are immutable - when you create two values containing the same data, they will always be the same. If they were mutable, you could change one and they wouldn't be equal anymore - that's why it makes more sense to use reference equality for mutable types.

like image 68
Tomas Petricek Avatar answered Dec 14 '22 09:12

Tomas Petricek