Hey folks,
I have a struct with some large arrays that need to be updated in place. The updates are not quite trivial and are in a function. What I would like to be able to do is something of the sort @. updatefunc( my_struct )
This seems to fail with an error ERROR: LoadError: MethodError: no method matching length(::my_struct)
. I have a minimally working example below. What is the reason for this behavior and is there a way to do what I would like to do (efficiently)?
struct test
x::Vector{Int}
end
function update( var::test )
var.x += 1
end
var = test( ones(Int, 5) )
@. var.x += 1
@show var
@. update( var ) # This call fails
Why can’t you do
function update!(var::test)
@. var.x += 1
end
update!(var)
Why do you want to broadcast over the struct (as opposed to broadcasting over the arrays contained in the struct)?
1 Like
It looks that you want to do
var.x .+=1
in your code you broadcast update on var which is not a collection
oops cross posting
Okay yeah this is easier. What about a slightly separate case, where an array needs to be updated in place by a quantity computed from a struct? e.g.,
struct test
x::Int
end
# Compute a generally complex quantity from members of a struct
function update( var::test )
return var.x
end
var = test( 1 )
myarray = zeros(5)
@. myarray += update( var ) # fails
The @.
will transform update(var)
to update.(var)
, which is not what you want. Just put the .
on the +=
where you want it: myarray .+= update(var)
Ah I didn’t notice that @.
was putting the .
everywhere. Thanks!
It also works if you define:
Base.broadcastable(x::test) = Ref(x)
which you should often do for new data types if you want to treat them as “scalars” (rather than containers) for broadcasting.
You can alternatively write myarray .+= update(var)
explicitly as noted above, or “opt-out” the update
function from @.
with @. myarray += $update(var)
.
I’ve been hoping to make this more explicit in the manual: many types should define broadcastable(o) = Ref(o) by stevengj · Pull Request #44093 · JuliaLang/julia · GitHub
1 Like