views:

169

answers:

3

Hello F# folks,

Suppose we have a Matrix class in F# and you overload the (+) operator. Then, we will have something like this:

type Matrix(n : int, m : int) = 
    ...
    static member (+) (A : Matrix, B : Matrix) = 
        let res = new Matrix(A.Dim1, A.Dim2) // suppose A and B have the same dimension
        ... // compute here the sum
        res

Comparing to C/C++, we would have something like this:

static const Matrix operator+(const Matrix& A, const Matrix& B)
{
    Matrix res(A.Dim1(), A.Dim2());
    ... // compute here the sum
    return res;
}

Now, observe that in F#, the matrix res is allocated in the heap memory, in contrast with the C++ version, that allocates res in the stack memory.

So far so good. Observe what happens when we want a "reference" to the result of the sum operation in both versions:

Matrix result = A + B; // deep copy in C++ (because res has to be destroyed after its return)

let result = A + B // shallow copy in F# (res was allocated in the heap memory)

Am I missing something here or the (+) operator in F# ends up being more efficient than its counterpart in C/C++, because of the shallow and deep copy behavior?

+2  A: 

Yep, F# (as C# and VB.NET) passes objects (class instances) by reference (so no copies created), if you use structs (in C#, not sure if you can create such a thing in F#) then they are passed by value (thus copies are created). Note that in C++ you can do it both ways too. But, yes, the way you propose your example, the F# solution is going to be more efficient.

Alas, somebody would probably point out that if you make Matrix a mutable object then you'll be even more performant (as no new Matrix objects need to be created), but then you loose all of the goodness of immutability.

Edgar Sánchez
+3  A: 

Usually, it is faster to keep data on the stack. And commercial-grade C++ compilers will often use the "return value optimization".

But until you start to actually measure the performance, you will never know which is faster. There are too many factors involved.

wmeyer
Thank you for the link. I never heard about return value optimization. Note that I could work with pointers in the C++ implementation, but this would be cumbersome and resulting in a very ugly and it would be not as straightforward as the one I provided. With return value optimization, it seems that the compiler does this low-level job for you. Very interesting. I would like to know if this is possible in C# and F#.
Allan
+2  A: 

.NET has reference and value types, and value types are allocated on the stack (unless they're part of a reference type, but let's not get carried away). In C# you would declare them with the class and struct keywords, respectively.

While this is not really part of the F# type declaration semantics, you can tell the compiler to create a particular type as a value type, by using the [<Struct>] attribute.

Alexander Rautenberg
Thank you for pointing out the [<Struct>] attribute, one more thing I learn trying to answer at stackoverflow. :-)
Edgar Sánchez