# Question regarding references

Could someone please help me understand references a bit better . I see several related questions have been asked and answered. I read them over and they did help a bit but I’m still not sure how to do what I would like.

I have a fairly complicated tree of structures containing various data types that may need changed based upon references from arbitrary points within the tree.
To create an example without the tree:

``````julia> A = 5
5
julia> B = A
5
julia> B === A
true
``````

However, I obviously cannot assign a value to B in the following way:

``````julia> B = 3
``````

Because I am saying that B is now a number instead of a reference to A. At least that is my understanding… What I do not see is how I can assign 3 to A through B. I hope I am explaining myself clearly.

I would really appreciate any help I can get on this. It’s probably something simple . Thanks!

1 Like

I believe I have read that some time back but it has a few details that I had forgotten about. Great information, Thanks! I am still not sure how to deal with my specific case though. Much of the information in that article focuses on a specific case (arrays). It may apply to my question but I don’t see how because A could represent a value in an Array or not and B is not an Array.

I would like to assign to A using B …so that when I assign to B the value of A is changed.

Thanks again for pointing that blog out to me.

I am assuming that you are using some sort of container, eg

``````mutable struct C{T}
x::T
end

A = C(1)
B = A
A.x = 2
B # now has 2
``````
1 Like

Sure, here’s an example:

``````# Ok, my container looks something like this:

julia> mutable struct NodeInTree
w::Array{Int64,1}
x::Int64
y::Any
end

# a tree would be composed of nodes that are mostly similer.
julia> nodeOne = NodeInTree( [1,2,3], 25, nothing )
NodeInTree([1, 2, 3], 25, nothing)

julia> nodeTwo = NodeInTree( [4,5,6], 50, nodeOne.w[2] )
NodeInTree([4, 5, 6], 50, 2)

# Now we can add in that missing binding...
julia> nodeOne.y = nodeTwo.x
50

# we can see they are identical:
julia> nodeOne.y === nodeTwo.x
true

# However upon assignment...
julia> nodeTwo.x = 3
3

julia> nodeOne.y
50

julia> nodeOne.y === nodeTwo.x
false

``````

If I understand your problem correctly, making `x` and `y` container types, eg `Ref`, or something defined for the purpose like my `C` above, may help.

1 Like

To follow on with @Tamas_Papp’s advice, the summary is that, no matter what, doing `B = 2` will never change the contents of some other variable. The only thing it does is apply the label “B” to a new value, regardless of what that label used to be applied to. On the other hand, mutating the contents of B can affect the contents of A, if they refer to the same mutable object. You can mutate contents by, for example, setting an array element, setting a Ref, or setting an object field.

All of the following are ways to achieve what you want:

• use an Array:
``````julia> A = [1]
1-element Array{Int64,1}:
1

julia> B = A
1-element Array{Int64,1}:
1

julia> B[1] = 5
5

julia> A[1]
5
``````
• use a Ref (similar to a zero-dimensional Array holding one object)
``````julia> A = Ref(1)
Base.RefValue{Int64}(1)

julia> B = A
Base.RefValue{Int64}(1)

julia> B[] = 5
5

julia> A
Base.RefValue{Int64}(5)

julia> A[]
5
``````
• use a container and mutate its contents
``````julia> mutable struct Foo
x::Int
end

julia> A = Foo(1)
Foo(1)

julia> B = A
Foo(1)

julia> B.x = 5
5

julia> A.x
5
``````

the key here is that all of the ways that work involve mutating an object or changing its contents with `B[] = 5` or `B[1] = 5` or `B.x = 5`. None of them involve re-assigning `B = 5` because that would just apply the `B` label to a brand-new piece of data, losing all connection between what the `B` and `A` labels mean.

8 Likes

Ok, that makes sense. It looks like you both have cleared up my misunderstanding. Thanks so much for heping me From your examples there @rdeits I think I can see where I had gone wrong.

If I understand correctly (from both of you) I cannot treat a simple variable as a reference …it must be a container!

I wrote about much the same thing on StackOverflow a while ago:

1 Like