Flatten.jl
Flatten.jl copied to clipboard
Major cleanup
This code is showing it's age and my inexperience writing Julia when I wrote this.
- [ ]
flatten,reconstructmodifymetaflattenetc should all have kwarg versions so people can actually understand what they do - [ ] hacks like getting the fieldname instead of tuple index are inconsistent and not worth the effort. They should be removed.
- [ ] functions should be the first argument - although this can be ambiguous when there are to method arguments.
- [ ]
flattenableshould not be used by default, see #20 - [ ] clearer language/kw args around querying should be used like
selectandskipinstead ofuseandignore - [ ] ultimately some cleaner lens-like logic should be defined for expressing what
nestedactually does in a clear way. Recursive@generatednesting needs to be formally wrapped somehow. Or use lenses if they can match the performance?
Maybe instead if a new package was written called ObjectQueries.jl people would better understand what you can do with it, and it could be rewritten from scratch:
query(x; select=Number)
# It still doesn't seem totally clear that `skip` skips actually the whole tree below the object:
query(x; select=Number, filter=flattenable, skip=SomeObject)
filter would actually be the first argument:
query(x; select=Number) do obj, fn
return getfield(obj, fn)
end
Maybe update without the bang for reconstruct:
This would be the default:
update(x; select=Number) do obj, fn, newvalue
return value
end
And in-place :
update!(x; select=Number) do obj, fn, newvalue
return setfield!(obj, fn, newvalue)
end
Whatever it is it can be composable with lens from Setfield.jl/Accessors.jl? Composing get seems straightforward - compose(FlattenLens{Params}(), @lens _.a) should get the a field from every Param object.
I'm not sure how nested @generated set and compose will "compose".
Flatten.jl would need to handle
set(obj, Composed(FlattenLens(), innerlens))
for set(ojb, compose, get(obj, composed)) == obj to work
You should only need to overload
(::FlattenLens)(obj) = # roughly whats currently in this package
Accessors.set(obj, lens::FlattenLens, val) = # not sure if this package covers immutable updates?
You should not need to think about composition. Accessors.jl will handle that for you.
Yeah I've been looking at how to get Accesors to do everything Flatten.jl does. I also rewrote this as a Setfiled Lens in a script before I knew about Accessors - its still using recursive @generated for the struct walking but composable with other lenses. Its fine and mostly seems to be compile-time operations.
The one thing missing for me in the Lens/Optic approach is context. With Flatten.jl you can get the field name and the type of the parent object for types that are filtered - which is really key to getting good output tables in https://github.com/rafaqz/ModelParameters.jl. That also lets you use FieldMetadata.jl to add more field context.
Context lenses don't follow the lens rules, so I'm not sure where to put them.