-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add setall() #68
add setall() #68
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for giving this a shot!
For me personally, the really useful cases would be, where getall
and setall
work with Vector
, while your PRs focus on the Tuple
case.
Implementation wise, I might have tried to use less getall
. I think in many places
where you call getall
you really only need to know length(getall(...))
or maybe Val(length(getall(...)))
. So maybe it makes sense to define a length_getall
that just computes this without actually forming unneeded intermediate getall
results?
OTHO I find it hard to reason about the optimizer and inference here so not sure if this would actually improve things.
I also find vectors important here, and Ideally, Do you have some else in mind?
Haven't tried that, but most likely it has to be yet another wannabe-recursive function generated with macros... I'm also thinking that maybe some insights from #23 development could be useful here? @rafaqz |
There are some optimizations one can do in the vector case, but that does not have to be in this PR. Like using views for splitting in setall and maybe having a BangBang style
One issue I remember with recursion is this: JuliaLang/julia#43296 (comment) OpticStyle(::Type{<:Optic}) = ...
OpticStyle(::Optic) = ... and only call on instances instead of types whenever possible. |
Makes sense, and I think it would be easy to do once the basic indexing
Curious what usecases you foresee for this, and what the semantic should be. Can it even be defined unambiguously for nontrivial cases? Like, |
The semantics would be that The main use case of
Can you give an example what potential ambiguity you see? |
Sorry, I misread and thought you are talking about |
I am a bit confused as to the relationship between this PR and |
The compiler does not like the kind of recursion used in #23. The PRs here infer better but don't allow recursion. For instance you can't get all |
These PRs and the potential differences were discussed in #63. @jw3126 touched on the implementation side, but there's also a design difference. Yes, for now the (already released) getall PR only supports non- |
But you are able to make it type stable for up to 4 levels of nesting currently? Could this be extended further? There probably is a reasonable limit (maybe <10) that would cover 99% of real world use cases. |
That's exactly what we did with getall :) Code in this PR is indeed typestable, but still not very efficient. It calls |
I think there is another subtle issue here. What is type stable here are cases, where the recursion depth is "obvious". Like |
That's true, |
You may want to look at how this problem was solved in Flatten.jl |
See my new update:
Comments and suggestions welcome! |
Co-authored-by: Jan Weidner <[email protected]>
I really like how neatly everything works together: julia> using Accessors, ForwardDiff, StaticArrays
# arbitrary function that takes an object
julia> f(x) = exp(x.a.b) - x.a.c
# differentiate wrt this part of x
julia> o = @optic _.a |> Properties()
# at this value of x
julia> x0 = (a=(b=1, c=2),)
julia> @btime ForwardDiff.gradient(v -> f(setall($x0, $o, v)), SVector(getall($x0, $o)))
12.127 ns (0 allocations: 0 bytes)
2-element SVector{2, Float64} with indices SOneTo(2):
2.718281828459045
-1.0 Will probably post in #appreciation after this gets released :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks a lot @aplavin this is awesome!
03b11fa
to
a9f483d
Compare
Copy-pasted till depth=4, seems to infer fine. The plan is to make the same kind of macro as with
getall
in the end, after all other questions are resolved.The implementation doesn't seem very clean, though - unlike
getall
. Improvement suggestions are welcome!Also, it's likely not the most efficient:
getall
is called more times than strictly needed. Would be great to remove extra calls, the complication is that we don't wantsetall
to recurse: currently, it only callssetall
with individual (not composed) optics.