Function argument not being updated correctly

hi,

i have a mutable struct representing an octree. its contains various info such as the list of all particle (another struct) inside it. I passed it as an argument of a function that should modify it. but only some part of the update are reflect in the main scope.

function verlet!(_tree)
    for part in _tree.points
        part.u += part.acc_x * dt/2
        part.v += part.acc_y * dt/2
        part.w += part.acc_z * dt/2

        part.x += part.u * dt
        part.y += part.v * dt
        part.z += part.w * dt

        # reset acc
        part.acc_x = 0
        part.acc_y = 0
        part.acc_z = 0
    end
    
    tmp = _tree.points
    _tree = nothing
    
    _tree = tree(1, _range)

    for p in tmp
       Tree.insert!(p, _tree)
    end

    for part in _tree.points
        query_acc!(_tree, part, 0.5, 10e16)
    end

    for (i, part) in enumerate(_tree.points)    
        part.u += part.acc_x * dt/2
        part.v += part.acc_y * dt/2
        part.w += part.acc_z * dt/2
    end

end

the problem is that in the main scope only the position and velocity of the particle are visibly changed, while the rest seems untouched.
the acceleration seems to be updated locally as the velocity are updated correctly but in the main scope its still equals 0. calling query_acc! in the repl change the acceleration value correctly.
same the global struct of the tree dont change. if i suppress the insert! part, the tree should be empty but in the main scope its still intact.

ps: i hope in clear enough.

These lines:

Re-bind the name _tree to a new value and initialize that value. After this point, the function has no way to modify the original value. Does it work correctly if you delete these lines?

2 Likes

It works correctly after your correction.

i just have to find a way to recompute/update the tree. now ! splitting the function in 2 would do the trick i guess but i would like to keep the current structure of the code.

Return the new tree, and call it as:

tree = verlet!(tree)

Better yet, instead of these lines you should mutate the fields of _tree directly.

You need to avoid any statement like _tree = something if you want the changes to be visible to the caller. Only do things like _tree.something = something

I think the key issue here is that you are confusing mutation (what you want to do) with assignment (_tree = ...). See e.g. Assignment and mutation · JuliaNotes.jl

3 Likes