Indexing (relatively) large nested list causes unintended mutation; doesn't occur after deepcopy

I generated a large amount of data from a simulation I’m working on, and was extracting values from the final list of structs via map. It only behaves after making a deepcopy, as you’ll see.

Basically: My function generates 131 lists, using the following call.

final_tests=map(x->replicate_runs(30,x),50:180)

Each of these lists contains a set of fields, some lists of up to 30 sub-lists, each of which contains 15 elements, notably Floats64s.

In my case, I used the following function to get the last element from my simulation output:
ans=map(x->final_tests[x][12],1:131)

This works as intended; however, the following code causes the list to predictably mutate:

ans[1] (prints lists of lists as expected)
ans[1] (prints first list in the previous list)
ans[1] (prints first element in previous list)
ans[1] (prints the scalar from the last one, ad infinitum)

When I first use b=deepcopy(ans), this behavior no longer occurs, and I can repeatedly index as much as I want. Any ideas what’s causing this? I’ll post code with permission from my PI, if this happens to be a weird bug that people have trouble reproducing.

On each line of the above, ans is changing to the result of the previous line as demonstrated below.

julia> a = [[1,2,3,],[4,5,6]]
2-element Vector{Vector{Int64}}:
 [1, 2, 3]
 [4, 5, 6]

julia> ans[1]
3-element Vector{Int64}:
 1
 2
 3

julia> ans[1]
1

julia> ans[1]
1

This is equivalent to if you have done the following:

julia> a = [[1,2,3,],[4,5,6]]
2-element Vector{Vector{Int64}}:
 [1, 2, 3]
 [4, 5, 6]

julia> b = a[1]
3-element Vector{Int64}:
 1
 2
 3

julia> c = b[1]
1

julia> d = c[1]
1

This is because ans is a special variable in the REPL. The value of the previously evaluated line is assigned to ans. Do not use ans as a variable name.

help?> ans
search: ans transpose transcode contains expanduser instances MathConstants

  ans

  A variable referring to the last computed value, automatically set at the
  interactive prompt.
3 Likes

Oh, I didn’t know that was a thing! Is there a way to turn on warnings before overwriting special variables?

There is an active discussion initiated by @BioTurboNick on this topic:
https://github.com/JuliaLang/julia/issues/43172

Honestly, this “feature” is probably only intuitive to those with a MATLAB background.

I’m not sure if the currently proposed solutions cover this case, so I think this post should be linked there. If you can comment on that issue and provide a link to to post, please do so. Otherwise, let me know and I can cross reference it.

I’m also thinking we should try to rename this topic so that someone else with a similar issue can more easily find it.

Perhaps the topic could be changed to “Indexing a variable named ans causes apparent unintended mutation”

2 Likes