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!
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.
# 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
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.
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!