Setting individual fields for struct in array

Could anyone suggest how to make the following:

struct A b::Int; c::Int end
as = [A(1, 1), A(2, 2)]
as[2].c = 3

work without resorting to:

  • mutable types
  • recreating A with a changed field

Ideally the produced llvm code might be similar to C equivalent (*pointer).c = 3, so the solution may involve Ref, unsafe methods etc. I checked the documentation, and some GitHub threads, but still can’t figure out how to do this and bypass Julia’s convention for immutability in this particular case.

I would recommend the following procedure to you:

struct A{T <: Integer} 
A(b::T, c::T) where T = new{T}([b], [c])

as = [A(1, 1); A(2, 2)]
as[2].c[1] = 3

Maybe it’s even possible to implement a specialized value to array conversion such that you do not have to use indexing in the last expression…

See these issues that give deep insights of what’s going on about this:

1 Like

In the meantime, you could try something like this

struct A{T<:Integer}
A(b::T, c::T) where {T<:Integer} = A{T}(Ref(b), Ref(c)), a::A) = print(io, "A(", a.b[], ", ", a.c[], ")")

as = [A(1, 1); A(2, 2)]
as[2].c[] = 3

Also, see this previous post Mutable field in immutable type and this comment on Immutable vs Type: reassignment via arrays and performance - #10 by jameson.

Thank you @cdsousa, but some code snippets which I encountered in these threads will be available in 1.0+, as I understood. At least methods mentioned are not available in 0.6. It is just very strange that there is no way to do something similar, even with some low-level code, in the current version. But I suspect that I’m missing something, if you would be able to provide a short snippet of working code, I would be grateful.

@pabloferz Is it possible to not uglify the struct definition, and obtain these RefValues in some other way?

@jonas-kr your solution introduces mutable objects (Vector), this makes the whole point of using immutable structs in array irrelevant.

1 Like