Accessing struct via Symbol

Dear all,

Is there a reason why this works:

struct Test1{A, B}
	a :: A
	b :: B
test1 = Test1(1., 2.)
test1.:a #1

but this does not work?

_a = :a
test1._a # type Test1 has no field _a

In my case I would like to update specific fields of Test1 via the Setfield.jl package. MWE:

using Setfield
function func1(test, fldsymbols)
	for sym in fldsymbols
		test = @set test.sym = 3.
	return nothing
func1(test1, (:a, ) ) #=ArgumentError: Failed to assign properties (:sym,) to object with fields (:a, :b). 
					    You may want to overload ConstructionBase.setproperties(obj::Test1{Float64, Float64}, patch::NamedTuple) =#

test1 = Setfield.@set test1.:a = 3. #this works fine though
test1.a #3

#Accessing via getfield(test1, sym) does not work and overrides the struct
test2 = Test1(4., 5.)
test2 = Setfield.@set getfield(test2, _a) = 6.
test2.a #type Float64 has no field a

In my real use case, changing only a single field of Test1 via Setfield.jl is cheaper than creating a new struct. I do not want to use a mutable struct to avoid possible bugs. The fieldnames for Test1 change though, so I usually store fields that I would like to change as symbols.

Best regards,

You could use @macroexpand to see what Setfield.@set does and then code it up without the macro. Maybe easier, Setfield.jl’s docs also tells you what is going on: Introduction · Setfield.jl.

1 Like

I think you’ll need to construct your Lens manually (but Setfield makes that very easy):

julia> struct Foo

julia> x = Foo(Foo(1,2),2)
Foo(Foo(1, 2), 2)

julia> p = :a

julia> set(x, Setfield.PropertyLens{p}(), 5)
Foo(5, 2)

Thank you!

Just so I understand correctly: Setfield.set will always create a new struct, and not inplace replace the fields? I.e.

using Setfield
x =  Foo(1., 2.)
function func1(foo, val)
	for sym in fieldnames( typeof(foo) )
		foo = Setfield.set(foo, Setfield.PropertyLens{sym}(), val)
	return foo
x.a #1.00
y = func1(x, 3.)
y.a #3.00
x.a #1.00

Thank you!

I will have a look at it to understand it better. I am trying to understand Macros better but it is a tough journey.

Yes, you’re using immutable structs after all – it’s not legal to modify their fields.