jw3126 / Setfield.jl

Update deeply nested immutable structs.
Other
167 stars 17 forks source link

Setting properties #90

Closed cstjean closed 5 years ago

cstjean commented 5 years ago

I'm interested in something like

@set object.property.x = 10

Can I support it? I get an error from assert_hasfields because, of course, property is not a field of object. I'd like to be able to implement setproperty(::Object, value, sym), similar to Base.setindex, which would return a new object with that property modified. Is that possible?

jw3126 commented 5 years ago

Yes! You need to overload Setfield.setproperties(obj, patch::NamedTuple). In the next few days/weeks this is moved to the tiny dependency ConstructionBase, see also https://github.com/JuliaObjects/ConstructionBase.jl/pull/1 So in future you only need to depend on ConstructionBase and overload ConstructionBase.setproperties(obj, patch::NamedTuple)

jw3126 commented 5 years ago

See for an example here: https://github.com/jw3126/Setfield.jl/blob/51bf0965e16bbb0a3abf5c97260bc7408eccb029/test/test_core.jl#L398

cstjean commented 5 years ago

It seems to work great, thank you!

cstjean commented 5 years ago

BTW, I haven't followed the entire discussion around constructor_of, but wouldn't it make sense to rewrite Setfield.jl around setproperties, with a fall-back to the constructor when it's not implemented? Relying on the constructor never felt quite right to me.

jw3126 commented 5 years ago

I would say that Setfield.jl is already designed around setproperties. The default implementation just uses constructor_of. Try

Setfield.setproperties(MyType, patch) = ...
Setfield.constructor_of(::Type{<:MyType}) = error()

And Setfield.jl should work fine with MyType.