Broadcasting with functions of structs

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