Mutating arrays not supported

@mcabbot, thank you for your feedback and the example.

After more reading, I think I understand the distinction between an assignment (where a variable points to) and a mutation (changing its values). A mutation will not change the objectid but an assignment will.

Yet, inside the custom layer, I can create new arrays in memory – with or without assignment: for example, these are all allowed:

  • deepcopy(x_out)
  • x_copy = deepcopy(x_out)
  • sin.(x_copy)
  • x_2 = sin.(x_copy)

The sin.(x_copy) in particular is okay (apparently) because it creates a new array but does not change one. Likewise, your example using vcat works (apparently) because it’s building an array, not changing one.

To generalize your vcat example for an arbitrary number of rows, I see on the REPL that the following works:

x_out_mod = vcat([x_out[i:i,:] for i in 1:size(x_out, 1)]...) 

To apply elements of an array f of functions to each row, we’d just do

x_out_mod = vcat([f[i].(x_out[i:i,:]) for i in 1:size(x_out, 1)]...) 

But even the first line doesn’t work inside the custom layer: I get a MethodError: no method matching iterate(::Nothing) which I can’t make heads or tails of. Replacing 1:size(x_out, 1) with 1:3 doesn’t help. Any ideas?

More conceptually, why aren’t mutations allowed? I thought I’d read that it has something to do with Flux not being able take gradients otherwise, but I don’t understand why it has no problem taking a gradient of a function broadcast to all elements and it would have a problem taking gradients of functions applied row-wise (which is my goal). Or why it’s okay to make new array but not to change an existing array (even one that is newly created and not tied to the struct).

2 Likes