Функция модифицирующего аргумента Юлия - PullRequest
0 голосов
/ 19 ноября 2018

У меня изменяемый составной тип,

 mutable struct MyType

      x::Array{Float64}

 end

И у меня есть функция, которую я хотел бы изменить на месте,

 function f(z::MyType)

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

      return z

 end

Кажется, это не работает для обновления z. Чего мне не хватает?

1 Ответ

0 голосов
/ 19 ноября 2018

z.x - это массив, поэтому необходимо указать z.x .+ 1 (обратите внимание на дополнительную точку), чтобы указать поэлементное добавление.

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

Эта функция делает обновление 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)

Выделения (по крайней мере) поняты из того факта, что он выделяет новый массив newx (копия z.x, где каждый элемент увеличивается на единицу), который затем устанавливаетсябыть новым массивом, назначенным z.x.Исходный массив, который был назначен z.x ранее, теперь потерян (и будет скопирован).

Предположительно, вы хотите изменить массив, назначенный z.x вразместить без создания промежуточного массива.Этого можно достичь, написав

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

Обратите внимание на .= вместо =, который назначает на месте (вы можете думать о поэлементном назначении).Это дает

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

Обратите внимание, что вы могли бы написать это гораздо короче

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