1
votes

I have a mutable composite type,

 mutable struct MyType

      x::Array{Float64}

 end

And I have a function which I would like to modify it in place,

 function f(z::MyType)

      newx = z.x + 1
      z.x = newx

      return z

 end

This does not seem to work to update z. What am I missing?

1

1 Answers

4
votes

z.x is an array so one must write z.x .+ 1 (note the extra dot) to indicate element-wise addition.

function f(z::MyType)
      newx = z.x .+ 1
      z.x = newx
      return z
 end

This function does update z:

julia> z = MyType(rand(1:10, 4))
MyType([10.0, 7.0, 2.0, 2.0])

julia> f(z)
MyType([11.0, 8.0, 3.0, 3.0])

julia> z
MyType([11.0, 8.0, 3.0, 3.0])

julia> @btime f($z);
  886.115 ns (4 allocations: 208 bytes)

The allocations are (at least) understood from the fact that it allocate a new array newx (a copy of z.x where every element is increased by one) which is then set to be the new array assigned to z.x. The original array, which was assigned to z.x before, is now lost (and will be gc'ed).

What you presumably want to do is modify the array that is assigned to z.x in-place without creating an intermediate array. This can be achieved by writing

function f(z::MyType)
      z.x .= z.x .+ 1 # or equivalently z.x .+= 1
      return z
end

Note the .= instead of = which assigns in-place (you can think of an elementwise assignment). This gives

julia> @btime f($z);
  372.284 ns (2 allocations: 48 bytes)

Note that you could write this much shorter as well

f(z::MyType) = (z.x .+= 1; z)