# Pointer-like field in a struct?

**URL:** <https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835>\
**Category:** General Usage\
**Created:** [February 6, 2024, 8:31pm UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835 "2024-02-06T20:31:00Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ferran\_Mazzanti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ferran_mazzanti/32/7458_2.png) [@Ferran\_Mazzanti](https://discourse.julialang.org/u/Ferran_Mazzanti)\
**Post date:** [February 6, 2024, 8:31pm UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835/1 "2024-02-06T20:31:00Z")

</div>

Hi,  
I hope somebody here can help me with this one.  
I’m building a Monte Carlo code for a system of particles. Position coordinates of these N particles are stored in a 3xN array of coordinates r[:,:], like for instance for N=5  
‘’’  
0.0719552 0.820621 0.169617 0.336838 0.620763  
0.218954 0.198641 0.793058 0.661784 0.32143  
0.448448 0.377976 0.533512 0.278445 0.821139  
‘’’  
where each particle sits in a different column, and rows indicate x,y and z for that particle, respectively.

Now I need to define an object (called a bead) for each of these particles, which I want to define in a mutable struct.That’s because every particle has some simulation parameters corresponding to it, and its own coordinates, together with the coordinates of its left particle, and the coordinates of its right particle. Then, along the simulation, the particle positions change according to a Metropolis criteria. What I would like to do, however, is to perform these coordinates changes in r[:,:], but such that the changes automatically apply to the coordinates in the beads. I have tried to define the beads as in  
‘’’  
mutable struct Bead{T}  
δt :: T;  
rleft :: Array{T};  
rright :: Array{T};  
Bead{T}() where T = new();  
end  
‘’’  
so that I can do  
‘’’  
kind=Float32  
b1 = Bead{kind}();  
b2 = Bead{kind}();  
b1.δt = b2.δt = 0.01;  
b1.rleft = view(r,:,2);  
b1.rright = view(r,:,3);  
b2.rleft = view(r,:,3);  
b2.rright = view(r,:,4);  
‘’’  
hoping that, being a view what I use, changes in r[:,:] are automaticaly updated to b1.rleft, b1.rright, b2.rleft and b2.rright.  
But that does not really work, and I think that this is becasue I define  
rleft and rright in the Bead struct as arrays, which copy the value they get  
at the point I initialize them, but do not get updated when r[:,:] is updated.  
If I was writting the code in C, I could define the rleft and rright fields in the Bead struct as pointers to r[:,:], which would then solve the problem. But in Julia… I don’t know.

So the question is: is there a way to implement this pointer-like behaviour?  
Something that would automatically update the rleft and rright fields in b1 and b2 when changes in r[:,:] are prodced…

Thanks in advance,

Ferran.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [February 6, 2024, 8:33pm UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835/2 "2024-02-06T20:33:22Z")

</div>

This should already work. Julia uses pass by sharing rather than pass by value. Values do not get copied unless you copy them.

---

<div class="post-metadata">

**Author:** ![Ferran\_Mazzanti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ferran_mazzanti/32/7458_2.png) [@Ferran\_Mazzanti](https://discourse.julialang.org/u/Ferran_Mazzanti)\
**Post date:** [February 6, 2024, 8:49pm UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835/3 "2024-02-06T20:49:54Z")

</div>

Uhmm… don’t get it to work.  
Here’s what I tried:

```julia
mutable struct Bead{T}
    δt :: T;
    rleft :: Array{T};
    rright :: Array{T};
    Bead{T}() where T = new();
end

kind = Float32;

# define an array of positions from part of a chain
# 
r = rand(3,5)

3×5 Matrix{Float64}:
 0.74328 0.253234 0.506628 0.581835 0.0087231
 0.612277 0.934715 0.723907 0.380912 0.537104
 0.374414 0.741888 0.985717 0.174058 0.0596843

b1 = Bead{kind}();
b2 = Bead{kind}();

b1.rleft = view(r,:,2);
b1.rright = view(r,:,3);
b2.rleft = view(r,:,3);
b2.rright = view(r,:,4);

hcat(b1.rright, b2.rleft)

3×2 Matrix{Float32}:
 0.506628 0.506628
 0.723907 0.723907
 0.985717 0.985717

r[:,3] = ones(3)
display(r)

3×5 Matrix{Float64}:
 0.74328 0.253234 1.0 0.581835 0.0087231
 0.612277 0.934715 1.0 0.380912 0.537104
 0.374414 0.741888 1.0 0.174058 0.0596843

hcat(b1.rright, b2.rleft)

3×2 Matrix{Float32}:
 0.506628 0.506628
 0.723907 0.723907
 0.985717 0.985717

```

so you see, the coordinates in b1.rleft etc are not updated to the new values ☹

Best,

Ferran.

​

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [February 6, 2024, 8:54pm UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835/4 "2024-02-06T20:54:45Z")

</div>

If you change `Bead` to

```julia
mutable struct Bead{T}
    δt :: T;
    rleft :: AbstractArray;
    rright :: AbstractArray;
    Bead{T}() where T = new();
end

```

it would work. The problem is that there is no way to make a subarray of a `Matrix{Float64}` fit into an `Array{Float32}

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [February 6, 2024, 9:05pm UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835/5 "2024-02-06T21:05:12Z")

</div>

Why not make the abstract array type a parameter?

```julia-repl
julia> mutable struct Bead{T, A <: AbstractArray{T}}
           δt :: T
           rleft :: A
           rright :: A
           function Bead(rleft::A, rright::A) where {T, A <: AbstractArray{T}}
               new{T,A}(zero(T), rleft, rright)
           end
       end

julia> kind = Float32;

julia> r = rand(kind, 3, 5);

julia> b1 = Bead(view(r,:,2), view(r,:,3))
Bead{Float32, SubArray{Float32, 1, Matrix{Float32}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}}(0.0f0, Float32[0.29957736, 0.95468074, 0.19946498], Float32[0.6553544, 0.96422833, 0.7301229])

julia> b2 = Bead(view(r,:,3), view(r,:,4))
Bead{Float32, SubArray{Float32, 1, Matrix{Float32}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}}(0.0f0, Float32[0.6553544, 0.96422833, 0.7301229], Float32[0.1161111, 0.386643, 0.23078555])

julia> hcat(b1.rright, b2.rleft)
3×2 Matrix{Float32}:
 0.655354 0.655354
 0.964228 0.964228
 0.730123 0.730123

julia> r[:,3] .= 1
3-element view(::Matrix{Float32}, :, 3) with eltype Float32:
 1.0
 1.0
 1.0

julia> r
3×5 Matrix{Float32}:
 0.229182 0.299577 1.0 0.116111 0.27342
 0.352749 0.954681 1.0 0.386643 0.952313
 0.993329 0.199465 1.0 0.230786 0.232765

julia> hcat(b1.rright, b2.rleft)
3×2 Matrix{Float32}:
 1.0 1.0
 1.0 1.0
 1.0 1.0

```

To clarify, the original issue is that you have declared the field types to be an `Array{T}`. `view` creates a `SubArray{T}`. When assigning to a field, Julia will _implicitly_ convert the right hand side type to the field type. In doing so, it makes a copy of the array.

To avoid making the copy, we need to make the field type compatible with the type being assigned so that no conversion and thus copying is done. Oscar’s method declares the field to be an abstract type.

In my example, I use a type parameter. This allows the field type of `rleft` and `rright` to be concretely determined from the concrete type of the `Bead`.

---

<div class="post-metadata">

**Author:** ![Ferran\_Mazzanti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ferran_mazzanti/32/7458_2.png) [@Ferran\_Mazzanti](https://discourse.julialang.org/u/Ferran_Mazzanti)\
**Post date:** [February 6, 2024, 9:10pm UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835/6 "2024-02-06T21:10:35Z")

</div>

Hi guys,

Great answers! I’ll try both and see, probably tomorrow morning.  
And btw, I did not now that struts could use parameters, which is something I thought about but believed to not be possible. Thanks for that piece of info, too 🙂

Best regards,

Ferran

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 6, 2024, 9:59pm UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835/7 "2024-02-06T21:59:41Z")

</div>

> [@Ferran\_Mazzanti](#):
>
> Position coordinates of these N particles are stored in a 3xN array of coordinates

Note that this is a classic case where you should consider StaticArrays.jl, i.e. use a length-N array of 3-component `SVector`s, e.g. `Vector{SVector{3,Float64}}`. Under the hood, the storage is the same as a 3xN array, but `SVector` is typically much easier to work with, and often faster because all of the length-3 loops will be unrolled.

e.g. you can just do `r[3] = r[1] + r[2]` set the third vector to the sum of the first two, and it allocates no temporary arrays on the heap and all the loops are unrolled: it just does 3 additions and an assignment. In contrast, `r[:,3] = r[:,1] + r[:,2]` allocates a temporary array (unless you use dot operations), and also involves a runtime loop (because the compiler doesn’t know that the loop is of length 3).

And if you want to do the same operation to all of the vectors, you can use broadcasting, e.g. `r .= update.(r)` will call `r[i] = update(r[i])` on every element of `r`, and since these are `SVector`s the `update` function can just use natural vector operations and doesn’t need to worry about allocations of 3-component vectors.

---

<div class="post-metadata">

**Author:** ![Ferran\_Mazzanti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ferran_mazzanti/32/7458_2.png) [@Ferran\_Mazzanti](https://discourse.julialang.org/u/Ferran_Mazzanti)\
**Post date:** [February 14, 2024, 9:56am UTC](https://discourse.julialang.org/t/pointer-like-field-in-a-struct/109835/8 "2024-02-14T09:56:59Z")

</div>

Hi again,

yesterday I found the time to test the proposals and thanks, yes, they work well 🙂  
One thing that I liked was the parametrized version proposed by @mkitti, but there is something I’d like to avoid. And that concerns the initialization at the end of the deffinition

```julia
function Bead(rleft::A, rright::A) where {T, A <: AbstractArray{T}}
               new{T,A}(zero(T), rleft, rright)

```

as it it, the new() part has to say something about all fields in the struct. If you look at my original (non-working) version, I just write new() because I prefer to  
initialize things externally. I do that because most of my structs undergo field changes with time and I do not want to haveing to care about that every time.  
Yes I know this may not be the best practica, but it has worked for me so far and, honestly, I do not want to change that…  
So I was wondering if there is a way to just specify rleft and rright at initialization, or not specify anything about them until the object is created externally, or…  
Maybe you know a way to do that?

Best regards and thanks,

Ferran.
