As pointed out here https://github.com/JuliaLang/julia/pull/11430#issuecomment-105062641, here https://github.com/JuliaLang/julia/pull/11430#issuecomment-105281450 and in some of the comments on that issue, the naming convention for Ref and RefValue is probably not the best and causes some confusion.
I'd like to propose the following changes
Ref -> CRef, ARef (A for Abstract) or ByRef (proposed by @JeffBezanson)RefValue -> Ref (and export this)and leaving RefArray as it is.
As pointed out by @vtjnash, most of the time what people need is the abstract version, but for #11430 and #18965 having Ref to mean RefValue would be more convenient.
Also, quoting @StefanKarpinski
I think that simple concrete names should be used for simple concrete things; programming correctly to an abstraction requires awareness and care, so having a name that reminds you of that is a good thing.
I don't agree with those comments in either of those issues. Both of them seem to be trying to code against RefValue, but should actually be written against Ref. That is also precisely why RefValue is not exported.
I can see that it is possible we should have two levels of Ref describing whether something is a c-compatible reference (ptr-convertable) or a heap-allocated/gc-managed reference. This could be CRef and Ref, where RefValue{T} <: Ref{T} <: CRef{T}, but that would require changing the meaning of Ref. Or we could choose another similar name that describes the additional abstract behavior of RefValue (that of its reference being heap allocated by Julia's GC) such as HeapRef or GCRef (where RefValue{T} <: GCRef{T} <: Ref{T}).
The abstract type should be used in case where all these types are designed for. There s also the different use case for a mutable slot (I.e. a cheaper zero dimensional array) and it just happens that refvalue is the one that satisfies the requirements.
There s also the different use case for a mutable slot (I.e. a cheaper zero dimensional array) and it just happens that refvalue is the one that satisfies the requirements.
That's probably where the tension comes from. The need of that behavior in some places, the fact that there's already a type that behaves that way (but it's embedded into a type hierarchy envisioned for other uses) and the discomfort of duplicating code / defining a new type gives rise to these conflicting opinions. So a possible solution might need flexibility on one of these two fronts.
Irrespectively of that, I believe that the idea of introducing another level to distinguish c-compatible and gc-managed references is a good idea anyway. I like the RefValue{T} <: Ref{T} <: CRef{T} proposal better.
Another option is to allow uses of RefValue as a mutable slot and properly document when people can use it and leave clear when they should use the current Ref. Granted, that wouldn't prevent misuses. That can't be prevented in general and in occasions people need to be told or referred to the manual so that is clear anyway.
@yuyichao If Ptr <: Ref, shouldn't the documentation be fixed to note that?
Ref{T}
An object that safely references data of type T. This type is guaranteed to
point to valid, Julia-allocated memory of the correct type. The underlying
data is protected from freeing by the garbage collector as long as the Ref
itself is referenced.
When passed as a ccall argument (either as a Ptr or Ref type), a Ref object
will be converted to a native pointer to the data it references.
There is no invalid (NULL) Ref.
There is a NULL pointer, and Ptr isn't guaranteed to point to valid Julia-allocated memory. If Ptrs are Refs, then this documentation isn't correct.
Another possibility: rename RefValue to RefCell or Cell and export it.
To summarize discussion:
Any for passing mutable structs to C, this will require type asserts in C functionGet rid of Ref in ccall, use ptr instead
cfunction?
Yes, both.
So how do you express
cfunction(identity, Int, Tuple{Ref{Int}})?
cfunction(unsafe_load, Int, Tuple{Ptr{Int}}) ;)
That becomes quite annoy. Also the case for return type.....
Using Ref as an implicit unsafe_load is a pretty rare thing to do though. Don't think I've personally ever used it that way.
Explictly as implicit unsafe_load not really (a lot in testing code...), as general references to julia objects, a lot in callbacks https://github.com/stevengj/Cubature.jl/pull/23 .
Note that the code linked works for both mutable and immutable objects.
Would be good to have an owner for this one if it is to make feature freeze?
Do we have a timeline for feature freeze?
Do we have a timeline for feature freeze?
It was said on slack that it would be in a bit less than 3 weeks.
This is a good thing to announce on discourse. Some of us don't use slack.
@KristofferC just suggested there the same a couple of hours ago!
I think a final call has yet to be taken as some folks think it isn't enough time.
This doesn't seem important enough to bother with. The current system is a little confusing, but it works and no one has seen fit to fix it in a year.