Search code examples
loopsdictionaryjuliainteractiondictionary-comprehension

Problem with interlinked dictionaries in Julia


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

Solution

  • 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