Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Extract common functionality into fold #32
base: master
Are you sure you want to change the base?
Extract common functionality into fold #32
Changes from 2 commits
e4088e0
b3db3e2
94a9b05
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
I considered
_
-prefixing everything but didn't for now because these will probably become part of the public API at some point. Happy to prefix them if that's desired though.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.
Can I suggest calling this
usecache
? It's not so clear to me which way "safe" points, safe that we don't need the cache, or safe that we can use it?Also, why
ismutable
? This catches only the outermost wrapper, which I don't think ought to matter.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.
usecache
sounds better, changed.ismutable
is required because this function is called at every level of the tree. So if there is a string in a (possibly deeply) nested struct that otherwise contains all bitstype values,isbits
will fail and we will get a false positive. In factismutable
may be sufficient on its own, but in the spirit of not making too many assumptions around underspecified language behaviour (namely that all mutable structs have stable objectids) I've kept it in to be safe.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.
Style not logic, but could this be more tidily done as a
safeget!
function, rather than types on which Base's functions act? There is I think exactly one line which calls thisget!
on these types.Something like
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.
I had exactly this in an earlier draft, but unfortunately it's a breaking change (i.e. tests fail) because the default before was to unconditionally trust IdDict/objectid/===. So value types were being deduped via the cache. If we decide to call that a bug, then I can put this suggestion in place.
Another theoretical benefit of not hard-coding
usecache
would be allowing users to customize caching behaviour on a case-by-case basis. I haven't thought of a scenario that would require such a degree of customization yet (e.g.TiedArrays
could simply overloadusecache
), so we can cross that bridge when we come to it.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.
Right, my suggestion still leaves
usecache
as an overloadable function. It's not intended as a change of logic, just more compact & fewer types?Testing
isbits
etc. seems at all seems like a potentially breaking change, as it changes how many timesf
will be called (e.g. what doesfmap(println, (1,2,3,1,2,3))
print?). Maybe it depends how firmly you believef
must be pure... certainlyfcollect
is going to change.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.
Checking for
isbits
andismutable
is a hedge against an impuref
. IMO users would be more surprised iffmap(println, (1,2,3,1,2,3))
printed1\n2\n3\n
as it currently does.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.
Yes. I'm in favour of some such
usecache
check. But perhaps this can be factored out, and we can discuss it this one has the right rules. (Should it be any or all?) This seems largely orthogonal.The point of this comment though was to wonder whether all these structs are necessary.
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.
So to clarify, yea to calling the current behaviour a bug and unconditionally calling
usecache
if it helps get rid of the structs?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.
Note that
fmap
andfcollect
are still passing throughIdDict()
by default. The hope is that new functions either don't allow customization of the cache or use a "safer" default.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.
This is technically breaking (as can be seen from the test changes), but it's unclear to me how many users were relying on the breadth-first iteration order. The one example I found on JuliaHub, AlphaZero, was not. It's also odd that the original worked breadth-first when pretty much all other traversals based on functors are depth-first. So RFC, and happy to back this out if we consider it too breaking.
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.
I think it's fine to have this breaking change.
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.
I think that nothing now in Optimisers.jl now cares about the order taken by
fmap
.Of course the two halves of
destructure
care a lot and must match. I haven't completely understood how #31 would have to change; it currently usesfmap
for one half and something hand-written for the other.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.
The order in
fmap
has always been stable, things bringsfcollect
in line as it was the odd one out.