imateapot
imateapot

Reputation: 141

How to have pointer members in F#

I am stuck trying to write in F# something that I conceive well in C++: a class that has as a member a list of pointers to objects of the same type. Because I haven't succeeded, I'm only posting my chimeric attempt, with the list of pointers included (which obviously is not correct F# and does not compile).

As the stylized chimeric wish below shows, the idea would be to create a bunch of Freds, and then build assign their myListOfPointers as needed, before calculating f() of one particular Fred. I've added a large data member to make the case that Freds shouldn't be copied, but in my target application calling f() changes the state of the Fred, so it seems yet more important that each Fred should not store a copy of the others its f requires to compute but only a "reference or pointer" to those. If this calls for a complete redesign, please succinctly state the path to follow.

type Fred(bigData:float[]) = 
{
    let data_ = bigData
    let mutable l = [] // list of "pointers to Fred", if there were such a thing
    member s.myListOfPointers with set(z) = l <- z
    member s.f() =
        match l with
            | [] -> Array.sum data_
            | _ ->  l |> List.map (fun p -> (*p).f()) //This dereferencing * operator is C++ language for what I would like to do.
                |> List.map (fun x ->  x * x) |> List.sum  
}

Thanks!

Upvotes: 0

Views: 693

Answers (2)

phoog
phoog

Reputation: 43076

You can't have pointers to Fred in f#. Instead, you would just have a list of Freds. The actual contents of the list are in fact pointers to Freds, but the language doesn't conceptualize them that way. Instead, they are .NET object references. If you're unfamiliar with the concepts, read up on reference types vs. value types, otherwise known as classes (reference types) and structs (value types):

Classes and Structs (C# Programming Guide)

So your list just becomes a Fred list and the lambda variable p is not dereferenced; it is not a pointer to a Fred, its type is simply Fred. You might therefore rename it as f.

Upvotes: 1

Daniel
Daniel

Reputation: 47914

With a few minor tweaks, your code works:

type Fred(bigData:float[]) = 
    let data_ = bigData
    let mutable l = [] // list of "pointers to Fred", if there were such a thing
    member s.myListOfPointers with set(z) = l <- z
    member s.f() =
        match l with
            | [] -> Array.sum data_
            | _ ->  l |> List.map (fun (p: Fred) -> p.f())
                      |> List.map (fun x ->  x * x) |> List.sum  

The notable thing is the need for a type annotation on p prior to calling f(). This is because the type of l is not known at that point.

Upvotes: 1

Related Questions