Ref / Pointer Usage

Hi,

I would like to do the following

julia> type ZInt
           aint::Int
       end

julia> z = ZInt(4)
ZInt(4)

julia> ref = Ref(z.aint)
Base.RefValue{Int64}(4)

julia> ref.x = 3
3

julia> z
ZInt(4) 

I want the z to evaluate to ZInt(3)
How can i get this done?
Thanks

z[] = 3

1 Like

I want to edit the content of z using ref in this case.
Editing must be via ref like a pointer and as a result the z 's content will be changed.!

Thanks

The only sensible thing you can do is

ref = z
ref.aint=3
z
ZInt(3)

Obviously you could play pointer games. But ultimately, you want your ref to keep z alive, and the way to do this is ref=z. This emits mostly the same code as

ref=reinterpret(Ptr{Int},pointer_from_objref(z))
unsafe_store!(ref, 5)
z
ZInt(5)

It’s just that you don’t have to calculate / look up field offsets and the garbage collector keeps you safe. Afaik there is no advantage of using references; sometimes you might need pointers for performance if you want to store them in a bitstype, but this is always slightly ugly.

1 Like

Taking references to mutable fields is part of WIP: Make mutating immutables easier by Keno · Pull Request #21912 · JuliaLang/julia · GitHub, but we don’t have that feature yet.

Just asking for interest… if

mutable struct foo
x::Int64 
y::Int64 
end 
f=foo(1,2)

and I take a reference to f.y which has type Ref{Int64}, how will gc find out that the allocation it needs to keep alive starts 8 bytes prior? (ok, in reality it starts even earlier because of the typetag, but for gc purposes it needs to subtract 8)

Ref is not a concrete type. The field reference type will have all the information necessary.

So this would then be mostly code_native-equivalent to the following? (with the same limitations regarding storage as all non-bitstypes)

immutable foo_y_ref
parent::foo
end
Base.getindex(foo_y_ref) = parent.y
Base.setindex!(foo_y_ref, val) = (parent.y=val)
Base.pointer(foo_y_refl) = reinterpret(Ptr{Int64}, pointer_from_objref(parent)+8)

That is, the ref would be pointer-sized, and a type encoding offset would be created?

edit: and the concrete type would rather be something like Ref{foo, 2} because we refer to the second field of foo, instead of Ref{Int64, plain}? And maybe something something covariance this should become a subtype of an abstract Ref{Int64, abstract}?

Yes.

Ideally not. There’s basically no point to store it in the type.

No.

1 Like