I have a problem regarding values set in a dictionary. I don't understand why they are changed unintentionally within a loop. Here, x_exog["B_l_pre"][2] changed from 0.5 to 0.525, but I only specified x_exog["B_l_post"][2] to change. Why ?
## Parameters and set up the environment
# Set exogenous parameters
x_exog = Dict{String, Any}()
# set amenity
x_exog["B_l_pre"] = [1;0.5;2]
x_exog["B_h_pre"] = [1;0.5;2]
x_exog["B_l_post"] = x_exog["B_l_pre"]
x_exog["B_h_post"] = x_exog["B_h_pre"]
x_exog_baseline = x_exog
# define the parameters
shock = "amenity"
for run in ["baseline","pro_poor_program", "pro_rich_program" ]
# set the initial values for exogenous variables
local x_exog = x_exog_baseline
x_exog["run"] = run
x_exog["shock"] = shock
# define the policy shock
if shock == "amenity"
# improve amenity slum
if run == "pro_poor_program"
x_exog["B_l_post"][2] = x_exog["B_l_post"][2] * 1.05
elseif run == "pro_rich_program"
x_exog["B_h_post"][2] = x_exog["B_h_post"][2] * 1.05
else
x_exog["B_l_post"][2] = x_exog["B_l_post"][2] * 1.05
x_exog["B_h_post"][2] = x_exog["B_h_post"][2] * 1.05
end
end
print(x_exog["B_l_pre"][2], x_exog["B_h_pre"][2]) ###Why the loop has changed x_exog["B_l_pre"] and x_exog["B_h_pre"] ?????
end
CodePudding user response:
It's so simple. Because you said:
x_exog["B_l_post"] = x_exog["B_l_pre"]
And remeber that you specified the x_exog["B_l_pre"]
as:
x_exog["B_l_pre"] = [1;0.5;2]
So the x_exog["B_l_post"]
refers to the same object in the memory as the x_exog["B_l_pre"]
refers to. To avoid this, you can pass a copy of x_exog["B_l_pre"]
to the x_exog["B_l_post"]
:
julia> x_exog["B_l_post"] = copy(x_exog["B_l_pre"])
3-element Vector{Float64}:
1.0
0.5
2.0
julia> x_exog["B_l_post"][2] = 2
2
julia> x_exog["B_l_post"]
3-element Vector{Float64}:
1.0
2.0
2.0
julia> x_exog["B_l_pre"]
3-element Vector{Float64}:
1.0
0.5
2.0
As you can see, I changed the second element of the x_exog["B_l_post"]
into 2, but this change doesn't happen in the x_exog["B_l_pre"]
because these are two separated objects now.
CodePudding user response:
Julia uses pass-by-sharing (see this SO question How to pass an object by reference and value in Julia?).
Basically, for primitive types the assignment operator assigns a value while for complex types a reference is assigned. In result both x_exog["B_l_post"]
and x_exog["B_l_pre"]
point to the same memory location (===
compares mutable objects by address in memory):
julia> x_exog["B_l_post"] === x_exog["B_l_pre"]
true
what you need to do is to create a copy of the object:
x_exog["B_l_post"] = deepcopy(x_exog["B_l_pre"])
Now they are two separate objects just having the same value:
julia> x_exog["B_l_post"] === x_exog["B_l_pre"]
false
julia> x_exog["B_l_post"] == x_exog["B_l_pre"]
true
Hence in your case