Home > other >  Problem with interlinked dictionaries in Julia
Problem with interlinked dictionaries in Julia

Time:12-13

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

  • Related