Add deepcopy operator := to avoid bugs

When doing everyday data analysis, avoiding bugs is often more time saving than having great code performance. One of my reoccurring bugs is that I forget that z=x doesn’t create a copy of x if x is an array.

Therefore I suggest to add a new operator := which assigns by creating a deepcopy.

In the same spirit, a colon at the end of a function name could create deepcopies of the function arguments when passed to the function (such that in my_fun:(x) the input variable x can be manipulated without affecting the value outside the variable outside the function).

By using the above operator and function-syntax I agree to the resulting performance penalty. If the code needs to be optimised for speed at a later stage, it is not very hard to inspect the code, check that no variables are unintentionally changed, and remove the colon.

An assignment never copies, not for any type. It always rebinds the name z to point to the same thing that x binds (i.e. refers) to. If you’re thinking of something like z = x[1:3] and how that copies - it’s the x[1:3] part (the slice) that copies, not the assignment.

Also, your suggestion about : would change julia quite a lot - note that we’re not necessarily at that stage of development anymore.

3 Likes

Did you consider creating a macro that modifies your code the way you need (e.g. rewriting z = x to z = deepcopy(x))? Then you would be able to write something like this:

@copyall begin
    z = x                  # translated to z = deepcopy(x)
    u = my_fun(x)   # translated to u = my_fun(deepcopy(x))
    ...

end

A macro like that doesn’t work well with functions that modify their arguments intentionally - and you may not know if that happens, if the function doesn’t follow the ! convention. I suspect this will lead to more bugs than are prevented by deeply changing how julia feels & thinks about memory.

Isn’t it what the OP asked for?

1 Like

That is actually easy to implement:

(::Colon)(f::Function, args::Tuple) = f(map(deepcopy, args)...)
a = [1] 
b = [2]
copyto!:(a,b) # does not modify a
3 Likes

Hi Per,
That bit of code impressed me a lot! :slight_smile: :+1:
Thanks!!

Hi @dfdx
Thanks for your input, I will look into the solution with the macro!
PS. Per solved the function-call part of the original question.